### The problem
`http_request.get` seems to be somewhat broken (at least for …me) especially in combination with `max_response_buffer_size`
using the `http_request.get` function without `max_response_buffer_size` causes the esp to hang, and then it just spams
`[02:38:44][E][http_request.arduino:132]: Stream pointer vanished!` until it crashes
printing out the `body` via
```
char *ptr;
ptr = (char*)body.c_str();
ESP_LOGD("custom", "ptr: %s\n", ptr);
```
also shows that there are some weird characters in the beginning:
```
[12:59:25][D][custom:349]: ptr: a8
{"code":"XXX","product":{"brands":"XXX","code":"XXX","product_name":"XXX"},"status":1,"status_verbose":"product found"}
```
after the get call the body should only be composed of the json at the end, no idea where the "a8" and the line brak comes from
Also `max_response_buffer_size` does not seem to work as described in the documentation, for me, the number defined for `max_response_buffer_size` defines the number of characters the `body` holds, instead of the size of it in kB as mentioned in the doc
If I do this:
`max_response_buffer_size: 24`
Instead of what I showed above, the log will show
```
[02:55:05][D][custom:349]: ptr: a8
{"code":"XXXXXXXXXXX
```
If I put in 28 instead of 24 it will show 4 more characters and so on.
Increasing the size to over around 200 will result in a crash of the esp.
(I am not a C++ dev and this is my first time opening an issue on github, sorry if I messed anything up)
### Which version of ESPHome has the issue?
2024.6.1
### What type of installation are you using?
Home Assistant Add-on
### Which version of Home Assistant has the issue?
2024.6.3
### What platform are you using?
ESP32
### Board
wemos_d1_mini32
### Component causing the issue
http_request
### Example YAML snippet
```yaml
substitutions:
friendly_name: "Barcode-Scanner-Custom"
# Query ID for opentindb (https://opengtindb.org/api.php)
rest_opentindb_queryid: "XXX"
# I2C-Pins for Display
display_i2c_sda: GPIO21
display_i2c_scl: GPIO22
# I2C-Adress OLED Display
ssd1306_i2c_address: "0x3C"
# UART-Pins for Barcode-Scanner
uart_tx_pin: GPIO09
uart_rx_pin: GPIO10
# Pin Buzzer/Beeper
beeper_pin: GPIO16
esphome:
name: barcode-scanner-custom
friendly_name: Barcode-Scanner-Custom
on_boot:
then:
- lambda: id(last_ean).publish_state("Scan Barcode");
api:
encryption:
key: !secret api_key
services:
- service: request_ean
variables:
eancode: string
then:
- script.execute:
id: request_ean
ean: !lambda return eancode.c_str();
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
esp32:
board: wemos_d1_mini32
# ----------------------------------
# ---- CONFIG END ----
# ----------------------------------
ota:
- platform: esphome
password: !secret ota_pw
improv_serial:
captive_portal:
logger:
hardware_uart: UART0
# ---------------------------------------------
globals:
- id: xpos_ean
type: int
initial_value: "0"
- id: xpos_brand
type: int
initial_value: "0"
- id: xpos_prod
type: int
initial_value: "0"
- id: safetyCheck
type: bool
initial_value: 'true'
text_sensor:
- platform: template
id: barcode_scanner
name: "${friendly_name} Sensor"
on_value:
then:
- if:
condition:
and:
- lambda: 'return id(barcode_scanner).state != "unknown";'
- lambda: 'return id(safetyCheck) == true;'
then:
- script.execute:
id: request_ean
ean: !lambda return x.c_str();
- platform: template
id: last_ean
name: "${friendly_name} EAN"
- platform: template
id: last_brand
name: "${friendly_name} Brand"
- platform: template
id: last_product
name: "${friendly_name} Product"
uart:
id: uart_bus
baud_rate: 9600
tx_pin: "${uart_tx_pin}"
rx_pin: "${uart_rx_pin}"
debug:
direction: BOTH
dummy_receiver: true
after:
delimiter: "\n"
sequence:
- lambda: UARTDebug::log_string(direction, bytes);
- text_sensor.template.publish:
id: barcode_scanner
state: !lambda |
std::string s(bytes.begin(), bytes.end());
return s;
font:
- file: "_fonts/arial.ttf"
id: arial_font_18
size: 18
- file: "_fonts/arial.ttf"
id: arial_font
size: 20
glyphs: |
ß!?"%()+*=,-_.:°ø0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÜÖ abcdefghijklmnopqrstuvwxyzäüö€@<>/
i2c:
sda: "${display_i2c_sda}"
scl: "${display_i2c_scl}"
scan: false
frequency: 400kHz
id: i2c_bus
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: "${ssd1306_i2c_address}"
update_interval: 250ms
lambda: |-
it.print(id(xpos_ean), 0, id(arial_font_18), id(last_ean).state.c_str());
it.print(id(xpos_brand), 19, id(arial_font), id(last_brand).state.c_str());
it.print(id(xpos_prod), 40, id(arial_font), id(last_product).state.c_str());
int x_start, y_start, height;
int brand_width, prod_width, ean_width;
it.get_text_bounds(0, 0, id(last_ean).state.c_str(), id(arial_font), TextAlign::TOP_LEFT, &x_start, &y_start, &ean_width, &height);
it.get_text_bounds(0, 0, id(last_brand).state.c_str(), id(arial_font), TextAlign::TOP_LEFT, &x_start, &y_start, &brand_width, &height);
it.get_text_bounds(0, 0, id(last_product).state.c_str(), id(arial_font), TextAlign::TOP_LEFT, &x_start, &y_start, &prod_width, &height);
if (id(xpos_ean) > (-1*ean_width)-30 && ean_width>128) {
id(xpos_ean) -= 10;
} else {
id(xpos_ean) = 0;
}
if (id(xpos_brand) > (-1*brand_width)-30 && brand_width>128) {
id(xpos_brand) -= 10;
} else {
id(xpos_brand) = 0;
}
int prod_len = strlen(id(last_product).state.c_str());
if (id(xpos_prod) > (-1*prod_width)-30 && prod_width>128) {
id(xpos_prod) -= 10;
} else {
id(xpos_prod) = 0;
}
switch:
- platform: gpio
name: "${friendly_name} Buzzer"
pin: "${beeper_pin}"
id: beeper
http_request:
useragent: esphome/barcodescanner
timeout: 10s
id: http_request_data
verify_ssl: false
script:
- id: request_ean
parameters:
ean: std::string
mode: single
then:
- globals.set:
id: safetyCheck
value: 'false'
- switch.turn_on: beeper
- delay: 50ms
- switch.turn_off: beeper
- script.execute:
id: getEanData
ean: !lambda return ean.c_str();
- delay: 500ms
- text_sensor.template.publish:
id: barcode_scanner
state: unknown
- id: getEanData
parameters:
ean: std::string
mode: single
then:
- script.execute: clearProductData
- lambda: |-
ESP_LOGD("getEanData", "Scanned EAN: %s\n", ean);
- lambda: id(last_ean).publish_state(ean);
- script.execute:
id: refreshProductNameOpenfoodfacts
ean: !lambda return ean.c_str();
- lambda: |-
ESP_LOGD("getEanData", "Openfoodfacts result: %s\n", id(last_product).state.c_str());
- delay: 500ms
- if:
condition:
or:
- text_sensor.state:
id: last_product
state: 'null'
- text_sensor.state:
id: last_product
state: ''
then:
- script.execute:
id: refreshProductNameOpenTin
ean: !lambda return ean.c_str();
- lambda: |-
ESP_LOGD("getEanData", "OpenTinDb result: %s\n", id(last_product).state.c_str());
- delay: 2s
- if:
condition:
text_sensor.state:
id: last_product
state: 'null'
then:
- switch.turn_on: beeper
- delay: 1000ms
- switch.turn_off: beeper
else:
- switch.turn_on: beeper
- delay: 50ms
- switch.turn_off: beeper
- delay: 2s
- globals.set:
id: safetyCheck
value: 'true'
- script.execute: resetDisplay
- id: resetDisplay
mode: restart
then:
- delay: 10s
- script.execute: clearProductData
- lambda: id(last_ean).publish_state("Scan Barcode");
- id: clearProductData
mode: single
then:
- lambda: id(last_ean).publish_state("");
- lambda: id(last_brand).publish_state("");
- lambda: id(last_product).publish_state("");
- id: refreshProductNameOpenTin
mode: single
parameters:
ean: std::string
then:
- http_request.get:
capture_response: true
max_response_buffer_size: 172
url: !lambda |-
return (std::string) "https://opengtindb.org/?ean=" + ean + "&cmd=query&queryid=${rest_opentindb_queryid}";
on_response:
then:
- lambda: |-
char delimiter[] = "\n";
char *ptr;
ptr = strtok((char*)body.c_str(), delimiter);
ESP_LOGD("opengtin", "ptr: %s\n", ptr);
int i = 0;
char *name_line = NULL;
char *vendor_line = NULL;
while(ptr != NULL) {
if(i == 4){
name_line = ptr;
}
if(i == 5){
vendor_line = ptr;
}
ptr = strtok(NULL, delimiter);
i++;
}
ptr = strtok(name_line, {"="});
i=0;
while(ptr != NULL) {
if(i == 1){
ESP_LOGD("opengtin", "Name: %s\n", ptr);
id(last_product).publish_state(ptr);
}
ptr = strtok(NULL, delimiter);
i++;
}
ptr = strtok(vendor_line, {"="});
i=0;
while(ptr != NULL) {
if(i == 1){
ESP_LOGD("opengtin", "Firma: %s\n", ptr);
id(last_brand).publish_state(ptr);
}
ptr = strtok(NULL, delimiter);
i++;
}
- id: refreshProductNameOpenfoodfacts
mode: single
parameters:
ean: std::string
then:
- http_request.get:
capture_response: true
max_response_buffer_size: 172
headers:
Content-Type: application/json
url: !lambda |-
std::string url = "https://world.openfoodfacts.org/api/v2/product/" + ean + "?fields=brands,product_name,code";
ESP_LOGD("openFood", "API: %s\n", url.c_str());
return url;
on_response:
then:
- if:
condition:
lambda: |-
return response->status_code == 200;
then:
- lambda: |-
char *ptr;
ptr = (char*)body.c_str();
ESP_LOGD("custom", "ptr: %s\n", ptr);
json::parse_json(ptr, [](JsonObject root) -> bool {
std::string jsonStr;
id(last_brand).publish_state(root["product"]["brands"]);
id(last_product).publish_state(root["product"]["product_name"]);
return true;
});
```
### Anything in the logs that might be useful for us?
```txt
This is the log with max_response_buffer_size: 172
[12:59:24][D][uart_debug:158]: <<< "XXXXXXXXXXXXX"
[12:59:24][D][text_sensor:064]: 'Barcode-Scanner-Custom Sensor': Sending state 'XXXXXXXXXXXXX'
[12:59:24][D][switch:012]: 'Barcode-Scanner-Custom Buzzer' Turning ON.
[12:59:24][D][switch:055]: 'Barcode-Scanner-Custom Buzzer': Sending state ON
[12:59:24][D][switch:016]: 'Barcode-Scanner-Custom Buzzer' Turning OFF.
[12:59:24][D][switch:055]: 'Barcode-Scanner-Custom Buzzer': Sending state OFF
[12:59:24][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state ''
[12:59:24][D][text_sensor:064]: 'Barcode-Scanner-Custom Brand': Sending state ''
[12:59:24][D][text_sensor:064]: 'Barcode-Scanner-Custom Product': Sending state ''
[12:59:24][D][getEanData:215]: Scanned EAN: \xxx#\xxx?
[12:59:24][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state 'XXXXXXXXXXXXX'
[12:59:24][D][openFood:337]: API: https://world.openfoodfacts.org/api/v2/product/XXXXXXXXXXXXX?fields=brands,product_name,code
[12:59:25][D][http_request.arduino:119]: Content-Length: -1
[12:59:25][D][custom:349]: ptr: a8
{"code":"XXXXXXXXXXXXX","product":{"brands":"XXX","code":"XXXXXXXXXXXXX","product_name":"XXX"},"status":1,"status_verbose":"product found"}
[12:59:25][E][json:103]: JSON parse error: InvalidInput
[12:59:25][D][getEanData:221]: Openfoodfacts result:
[12:59:25][W][component:237]: Component script took a long time for an operation (1286 ms).
[12:59:25][W][component:238]: Components should block for at most 30 ms.
[12:59:28][D][http_request.arduino:119]: Content-Length: 13
[12:59:28][D][opengtin:290]: ptr: error=1
[12:59:28][D][getEanData:237]: OpenTinDb result:
[12:59:28][W][component:237]: Component script took a long time for an operation (1870 ms).
[12:59:28][W][component:238]: Components should block for at most 30 ms.
[12:59:28][D][text_sensor:064]: 'Barcode-Scanner-Custom Sensor': Sending state 'unknown'
[12:59:30][D][switch:012]: 'Barcode-Scanner-Custom Buzzer' Turning ON.
[12:59:30][D][switch:055]: 'Barcode-Scanner-Custom Buzzer': Sending state ON
[12:59:30][D][switch:016]: 'Barcode-Scanner-Custom Buzzer' Turning OFF.
[12:59:30][D][switch:055]: 'Barcode-Scanner-Custom Buzzer': Sending state OFF
[12:59:42][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state ''
[12:59:42][D][text_sensor:064]: 'Barcode-Scanner-Custom Brand': Sending state ''
[12:59:42][D][text_sensor:064]: 'Barcode-Scanner-Custom Product': Sending state ''
[12:59:42][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state 'Scan Barcode'
This is the log with max_response_buffer_size not defined at all, defined with a value of over 200 or with it only being defined in one of the get functions:
[13:25:54][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state ''
[13:25:54][D][text_sensor:064]: 'Barcode-Scanner-Custom Brand': Sending state ''
[13:25:54][D][text_sensor:064]: 'Barcode-Scanner-Custom Product': Sending state ''
[13:25:54][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state 'Scan Barcode'
[13:26:16][D][uart_debug:158]: <<< "XXXXXXXXXXXXX"
[13:26:16][D][text_sensor:064]: 'Barcode-Scanner-Custom Sensor': Sending state 'XXXXXXXXXXXXX'
[13:26:16][D][switch:012]: 'Barcode-Scanner-Custom Buzzer' Turning ON.
[13:26:16][D][switch:055]: 'Barcode-Scanner-Custom Buzzer': Sending state ON
[13:26:16][D][switch:016]: 'Barcode-Scanner-Custom Buzzer' Turning OFF.
[13:26:16][D][switch:055]: 'Barcode-Scanner-Custom Buzzer': Sending state OFF
[13:26:16][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state ''
[13:26:16][D][text_sensor:064]: 'Barcode-Scanner-Custom Brand': Sending state ''
[13:26:16][D][text_sensor:064]: 'Barcode-Scanner-Custom Product': Sending state ''
[13:26:16][D][getEanData:215]: Scanned EAN: \xxx#\xxx?
[13:26:16][D][text_sensor:064]: 'Barcode-Scanner-Custom EAN': Sending state 'XXXXXXXXXXXXX'
[13:26:16][D][openFood:335]: API: https://world.openfoodfacts.org/api/v2/product/XXXXXXXXXXXXX?fields=brands,product_name,code
[13:26:17][D][http_request.arduino:119]: Content-Length: -1
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
[13:27:32][E][http_request.arduino:132]: Stream pointer vanished!
and this goes on infinitley until the device crashes
```
### Additional information
I have two `http_request.get` functions that do different things. Only if both of them have the `max_response_buffer_size` defined the system won't run into the `[02:38:44][E][http_request.arduino:132]: Stream pointer vanished!`-Error upon executing them