ESP32 HTTP Request get Data - Could not allocate memory for JSON document! Requested 0 bytes, free heap: 110580
The problem
StaticJsonDocument is empty
{
"telegram": [
"/ISk5MT174-0001",
"0.9.1(130203)",
"0.9.2(0230223)",
"0.0.0(00339188)",
"0.2.0(1.03)",
"C.1.6(FDF5)",
"1.8.1(0011404.409*kWh)",
"1.8.2(0023813.725*kWh)",
"2.8.1(0015608.962*kWh)",
"2.8.2(0000900.569*kWh)",
"F.F.0(0000000)",
"!"
]
}
Could not allocate memory for JSON document! Requested 0 bytes, free heap: 110580
1st log output shows the payload 2nd Error Could not allocate memory for JSON document 3rd log output shows no payload
Which version of ESPHome has the issue?
2023.2.4
What type of installation are you using?
Docker
Which version of Home Assistant has the issue?
No response
What platform are you using?
ESP32
Board
az-delivery-devkit-v4
Component causing the issue
http_request
Example YAML snippet
## ---------------------------------------------------
## TEST ESPLESEKOPF TELEGRAMS
## board: az-delivery-devkit-v4; framework: arduino; platform: platformio/espressif32 @ 5.2.0
## ---------------------------------------------------
## 2023.2.4|Flash: 4096kB Speed:40MHz Mode:DIO|
## Chip: ESP32 Features:WIFI_BGN,BLE,BT, Cores:2 Revision:3|
## ESP-IDF: v4.4.2|EFuse MAC: 78:21:84:9C:B2:AC|
## Reset: Software Reset CPU|Wakeup: Unknown
## ---------------------------------------------------
substitutions:
device_name_short: "esp-lesekopf2"
friendly_name: "Smartmeter"
device_description: "Smartmeter Device for Gridmeter ISKRA 2013 M13 1376, Drehstromzähler"
domain: !secret domain
appversion: "2.0.1"
service_url: !secret service_host
service: "mt174.gridmeter"
## ---------------------------------------------------
## device configuration
## ---------------------------------------------------
board: "az-delivery-devkit-v4"
uart_rx_pin: "GPIO17" # white
uart_tx_pin: "GPIO16" # orange
uart_baudrate: "300"
update_interval: "60s"
esp32:
board: az-delivery-devkit-v4
framework:
type: arduino
esphome:
name: "${device_name_short}"
comment: "${device_description}"
build_path: ./build/${device_name_short}
## ---------------------------------------------------
## WIFI Settings
## ---------------------------------------------------
wifi:
networks:
- ssid: !secret ssid3_name
password: !secret ssid3_pswd
priority : 1
- ssid: !secret ssid1_name
password: !secret ssid1_pswd
priority : 2
- ssid: !secret ssid2_name
password: !secret ssid2_pswd
priority : 3
domain: !secret domain
## ----------------------------------------------------------------------
## WEBSERVER Settings
## ----------------------------------------------------------------------
web_server:
port: 80
version: 2
local: true
## ---------------------------------------------------
## OTA Settings
## ---------------------------------------------------
ota:
password: !secret ota_pswd
on_error:
then:
- logger.log:
format: "OTA update error %d"
args: ["x"]
# ----------------------------------------------------------------
# Native API Component
# ----------------------------------------------------------------
api:
id: espapi
port: 6053
reboot_timeout: 0s
# ----------------------------------------------------------------
# Logger
# ----------------------------------------------------------------
logger:
id: mylogger
level: info
baud_rate: 0 #disable logging over uart
# ----------------------------------------------------------------
# HTTP
# ----------------------------------------------------------------
http_request:
id: http_request_data
useragent: esphome/mt174test
timeout: 10s
# ----------------------------------------------------------------
# Serial interface
# ----------------------------------------------------------------
uart:
id: my_uart
tx_pin: GPIO17 # white [TX] az-delivery-devkit-v4,
rx_pin: GPIO16 # orange [RX] az-delivery-devkit-v4,
baud_rate: 300
data_bits: 7
parity: EVEN
stop_bits: 1
rx_buffer_size: 512
debug:
direction: BOTH
after:
delimiter: "\r\n"
sequence:
- lambda: |-
UARTDebug::log_string(direction, bytes); //Still log the data
std::string str(bytes.begin(), bytes.end());
ESP_LOGI("UART", "DATA: %s",str.c_str());
## ---------------------------------------------------
## SCRIPTS
## ---------------------------------------------------
script:
- id: writeTelegram
parameters:
message: string
mode: queued
then:
- logger.log:
level: info
format: "Telegram message: %s"
args: ["message"]
- uart.write:
id: my_uart
data: !lambda |-
std::string str = message;
std::vector<uint8_t> vec(str.begin(), str.end());
return vec;
- uart.write:
id: my_uart
data: "\r\n"
- delay: 10ms
- logger.log: "Next Telegram message"
- id: getNetInfoData
mode: queued
then:
- http_request.get:
url: http://ip-api.com/json/
headers:
Content-Type: application/json
verify_ssl: false
on_response:
- if:
condition:
lambda: |-
return status_code == 200;
then:
- logger.log:
level: info
format: "Response status: %d, Duration: %u ms"
args:
- status_code
- duration_ms
- logger.log:
level: info
format: "Start telegramdata: %s"
args: ["id(http_request_data).get_string()"]
- id: getTelegramdata
mode: queued
then:
- logger.log:
level: info
format: "HTTP Request get Data"
- http_request.get:
url: !secret data_host
headers:
Content-Type: application/json
verify_ssl: false
on_response:
- if:
condition:
lambda: |-
return status_code == 200;
then:
- logger.log:
level: info
tag: "getTelegramdata"
format: "Response status: %d, Duration: %u ms"
args:
- status_code
- duration_ms
- logger.log:
level: info
tag: "getTelegramdata"
format: "Response telegramdata: %s"
args: ["id(http_request_data).get_string()"]
# {"telegram":
# [
# "/ISk5MT174-0001",
# "0.9.1(130203)",
# "0.9.2(0230223)",
# "0.0.0(00339188)",
# "0.2.0(1.03)", "C.1.6(FDF5)",
# "1.8.1(0011404.409*kWh)",
# "1.8.2(0023813.725*kWh)",
# "2.8.1(0015608.962*kWh)",
# "2.8.2(0000900.569*kWh)",
# "F.F.0(0000000)", "!"
# ]}
- lambda: |-
ESP_LOGI("script", "Decode Response");
json::parse_json(id(http_request_data).get_string(), [](JsonObject root) {
for (uint16_t i = 0; i < 12; i++) {
ESP_LOGI("parse", "telegram %d: %s",i,root["telegram"][i] );
}
});
- logger.log:
level: info
tag: "getTelegramdata"
format: "Response telegramdata: %s"
args: ["id(http_request_data).get_string()"]
- logger.log:
level: info
tag: "getTelegramdata"
format: "End telegram decoder"
- id: snddata
then:
- lambda: |-
uint16_t size = id(seltelegram).size();
for (uint16_t i = 0; i < size; i++) {
auto option = id(seltelegram).at(i);
auto value = option.value();
ESP_LOGI("script", "Option at %d is: %s", index, value.c_str());
id(writeTelegram).execute(value);
}
select:
- platform: template
name: "Select Telegram"
id: seltelegram
optimistic: true
options:
- "/ISk5MT174-0001"
- "0.9.1(130203)"
- "0.9.2(0230223)"
- "0.0.0(00339188)"
- "0.2.0(1.03)"
- "C.1.6(FDF5)"
- "1.8.1(0016519.075*kWh)"
- "1.8.2(0029595.323*kWh)"
- "2.8.1(0020656.624*kWh)"
- "2.8.1(0020656.624*kWh)"
- "F.F.0(0000000)"
on_value:
then:
- logger.log:
format: "Telegram Data: %s"
tag: "select"
args: ["x.c_str()"]
- lambda:
id(writeTelegram).execute(x.c_str());
## ---------------------------------------------------
## switches
## ---------------------------------------------------
switch:
- platform: restart
id: restart_device
name: ${friendly_name} restart
button:
- platform: template
name: 'Test: Get Telegram Data'
id: btnTestTelegramData
on_press:
- logger.log:
level: info
format: Get Data and decoder for telegram startet"
- script.execute: getTelegramdata
- platform: template
name: 'Test: Telegram Data'
id: btnTestTelegram
on_press:
- logger.log:
level: info
format: "Simple Testcase"
- script.execute: snddata
- platform: template
name: 'Test: IP Data'
id: btnGetNetInfoData
on_press:
- script.execute: getNetInfoData
.....
Anything in the logs that might be useful for us?
[13:07:15][I][main:413]: Get Data and decoder for telegram startet"
[13:07:15][I][main:267]: HTTP Request get Data
[13:07:15][I][getTelegramdata:290]: Response status: 200, Duration: 48 ms
[13:07:15][I][getTelegramdata:293]: Response telegramdata: {"telegram": ["/ISk5MT174-0001", "0.9.1(130203)", "0.9.2(0230223)", "0.0.0(00339188)", "0.2.0(1.03)", "C.1.6(FDF5)", "1.8.1(0011404.409*kWh)", "1.8.2(0023813.725*kWh)", "2.8.1(0015608.962*kWh)", "2.8.2(0000900.569*kWh)", "F.F.0(0000000)", "!"]}
[13:07:15][I][script:314]: Decode Response
[13:07:15][E][json:081]: Could not allocate memory for JSON document! Requested 0 bytes, free heap: 110580
[13:07:15][I][getTelegramdata:322]: Response telegramdata: <-- 2nd Log output empty !
[13:07:15][I][getTelegramdata:325]: End telegram decoder
Additional information
No response
current workaround:
If I save the (http_request_data) .get_string () to a text_sensor, I can continue to use it.
script:
- id: getTelegramdata
then:
- logger.log:
level: info
format: "HTTP Request get Data"
- http_request.get:
url: !secret data_host
headers:
Content-Type: application/json
verify_ssl: false
on_response:
- if:
condition:
lambda: |-
return status_code == 200;
then:
- lambda: |-
auto data = id(http_request_data).get_string();
id(telegraminfo).publish_state(data);
delay(100);
ESP_LOGI("script", "Decode Response %s", id(telegraminfo).state.c_str() );
json::parse_json(id(telegraminfo).state.c_str(), [](JsonObject root) {
ESP_LOGI("parse", "telegram raw %s", root["telegram"]);
for (uint16_t i = 0; i < 12; i++) {
ESP_LOGI("parse", "telegram %d: %s",i,root["telegram"][i] );
}
});
- logger.log:
level: info
tag: "getTelegramdata"
format: "Response telegramdata: %s"
args: ["id(telegraminfo).state.c_str()"]
- logger.log:
level: info
tag: "getTelegramdata"
format: "End telegram decoder"
text_sensor:
- platform: template
name: Telegram
id: telegraminfo
I just don't understand why json :: parse_json (id (telegraminfo) .state.c_str (), [] (JsonObject root) doesn't work.
What am I doing wrong?
Log:
[14:26:23][I][main:392]: Get Data and decoder for telegram startet"
[14:26:23][I][main:267]: HTTP Request get Data
[14:26:24][I][script:291]: Decode Response {"telegram": ["/ISk5MT174-0001", "0.9.1(130203)", "0.9.2(0230223)", "0.0.0(00339188)", "0.2.0(1.03)", "C.1.6(FDF5)", "1.8.1(0011404.409*kWh)", "1.8.2(0023813.725*kWh)", "2.8.1(0015608.962*kWh)", "2.8.2(0000900.569*kWh)", "F.F.0(0000000)", "!"], "timestamp": "2023-02-26T14:26:23"}
[14:26:24][I][parse:293]: telegram raw
[14:26:24][I][parse:295]: telegram 0:
[14:26:24][I][parse:295]: telegram 1:
[14:26:24][I][parse:295]: telegram 2:
[14:26:24][I][parse:295]: telegram 3:
[14:26:24][I][parse:295]: telegram 4:
[14:26:24][I][parse:295]: telegram 5:
[14:26:24][I][parse:295]: telegram 6:
[14:26:24][I][parse:295]: telegram 7:
[14:26:24][I][parse:295]: telegram 8:
[14:26:24][I][parse:295]: telegram 9:
[14:26:24][I][parse:295]: telegram 10:
[14:26:24][I][parse:295]: telegram 11:
[14:26:24][I][getTelegramdata:300]: Response telegramdata: {"telegram": ["/ISk5MT174-0001", "0.9.1(130203)", "0.9.2(0230223)", "0.0.0(00339188)", "0.2.0(1.03)", "C.1.6(FDF5)", "1.8.1(0011404.409*kWh)", "1.8.2(0023813.725*kWh)", "2.8.1(0015608.962*kWh)", "2.8.2(0000900.569*kWh)", "F.F.0(0000000)", "!"], "timestamp": "2023-02-26T14:26:23"}
[14:26:24][I][getTelegramdata:303]: End telegram decoder
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I think the real solution for the error message Could not allocate memory for JSON document! Requested 0 bytes is not to call id(http_request_data).get_string() without using the data. The function get_string() returns an empty string after the first call.
This code:
ESP_LOGI(RESPONSE, get_string(): [%s], id(http_request_data).get_string());
std::string response_data = id(http_request_data).get_string();
ESP_LOGI(RESPONSE, response_data: [%s], response_data.c_str());
if (!response_data.empty()) {
ESP_LOGI("JSON", "Parse");
json::parse_json(response_data, [](JsonObject root) {
id(switch_x).publish_state(root["value"]);
});
}
produces this log:
[I][RESPONSE:055]: get_string(): [{"id":"sensor-switch_state","value":1,"state":"1.0"}]
[I][RESPONSE:057]: response_data: []
or, if the empty check on response_data is omitted:
[I][RESPONSE:055]: get_string(): [{"id":"sensor-switch_state","value":1,"state":"1.0"}]
[I][RESPONSE:057]: response_data: []
[I][JSON:059]: Parse
[E][json:081]: Could not allocate memory for JSON document! Requested 0 bytes, free heap: 8257524
But if the first line is omitted:
[I][RESPONSE:056]: response_data: [{"id":"sensor-switch_state","value":1,"state":"1.0"}]
[I][JSON:058]: Parse
[D][sensor:094]: 'Switch': Sending state 1.00000 with 1 decimals of accuracy
In your first getTelegramdata there is a logger.log using id(http_request_data).get_string() before using the data (hence the empty response on the second call in the lambda). In the lambda there is no check for an empty response (hence the "Requested 0 bytes"). If you put something like the first line in my example above before your line with auto data = id(http_request_data).get_string(), you'll probably see the error again.
Currently This error is coming in my code 18:00:56 | [E] | [json:084] | Could not allocate memory for JSON document! Requested 0 bytes, free heap: 110580
` esphome: name: test
esp32: board: esp32dev framework: type: arduino
logger:
api: password: "123"
ota: platform: "esphome" password: "pakistan123"
wifi: ssid: "Digital Spyre" password: "DigitalSpyre@14321Nada"
ap: ssid: "Test Fallback Hotspot" password: "123456789"
captive_portal:
http_request: id: my_http_request verify_ssl: false
switch:
-
platform: gpio name: "Switch 1" pin: 25 id: "switch_1" on_turn_on:
- http_request.get: url: http://192.168.100.14:3000/switch1/on
- switch.turn_on: switch_2
on_turn_off: - http_request.get: url: http://192.168.100.14:3000/switch1/off
-
platform: gpio name: "Switch 2" pin: 26 id: "switch_2" on_turn_on:
- http_request.get: url: http://192.168.100.14:3000/switch2/on on_turn_off:
- http_request.get: url: http://192.168.100.14:3000/switch2/off
interval:
- interval: 30s
then:
-
http_request.get: url: http://192.168.100.15/fan/living_room_fan on_response: then: - lambda: |-
json::parse_json(body, [](JsonObject root) { // Extract the value field from the JSON response bool value = root["value"].as<bool>(); if (value) { id(switch_2).turn_on(); ESP_LOGI("HTTP_RESPONSE", "Switch 2 turned ON because value is true"); } else { ESP_LOGI("HTTP_RESPONSE", "Switch 2 not triggered, value is false"); } return true; });
-
web_server: port: 80 `
I fixed this by adding capture_response to the http_request block
- http_request.post:
url: http://rhome:8123/api/services/schedule/get_schedule?return_response
headers:
Content-Type: application/json
Authorization: !secret ha_token
capture_response: true
json:
entity_id: "schedule.lighting"