如何在ESPHome中构建传感器值字典/JSON对象并批量上报?
在ESPHome中实现高频传感器数据的批量收集与上报
核心思路
通过全局变量存储指定时长内的单键读数,定时计算合并值(平均值/自定义过滤),再通过HTTP请求上报合并后的JSON对象。
完整配置示例
# 基础配置 esphome: name: sensor-collector platform: ESP32 board: esp32dev # WiFi配置(按需修改) wifi: ssid: "your-wifi-ssid" password: "your-wifi-password" # 可选:WiFi断开重连设置 ap: ssid: "SensorCollector Fallback Hotspot" password: "fallback-password" captive_portal: # 日志输出(调试用) logger: baud_rate: 0 # 禁用串口日志,避免和传感器输入冲突 # HTTP请求组件,用于上报数据 http_request: useragent: esphome/sensor-collector timeout: 5s # 全局变量:存储每个传感器键对应的读数列表 globals: - id: sensor_readings type: std::map<std::string, std::vector<float>> restore_value: false initial_value: '{}' # 串口配置(假设传感器通过串口发送JSON数据,按需修改引脚和波特率) uart: rx_pin: GPIO3 baud_rate: 115200 data_bits: 8 parity: none stop_bits: 1 on_data_received: then: # 解析串口收到的JSON数据 - json.parse: id: input_json_parser data: !lambda "return std::string((const char*)data, len);" # 将解析后的键值对存入全局变量 - lambda: |- for (auto it = id(input_json_parser).begin(); it != id(input_json_parser).end(); ++it) { std::string key = it->first; float value = it->second.as<float>(); id(sensor_readings)[key].push_back(value); } # JSON解析器 json: - id: input_json_parser # 文本传感器(调试用,查看合并后的JSON) text_sensor: - platform: template id: averaged_data_json name: "Averaged Sensor Data" # 定时任务:每10秒执行一次数据合并与上报 interval: - interval: 10s then: - lambda: |- // 计算每个传感器的平均值 std::map<std::string, float> merged_data; for (auto& entry : id(sensor_readings)) { const std::string& key = entry.first; const std::vector<float>& values = entry.second; if (values.empty()) continue; // 计算平均值(可替换为其他过滤逻辑) float sum = 0.0f; for (float val : values) { sum += val; } merged_data[key] = sum / values.size(); // 可选过滤逻辑示例: // merged_data[key] = values.back(); // 取最新值 // merged_data[key] = *std::max_element(values.begin(), values.end()); // 取最大值 } // 生成最终JSON字符串 std::string json_output; JsonDocument doc; for (auto& entry : merged_data) { doc[entry.first] = entry.second; } serializeJson(doc, json_output); // 更新调试用文本传感器 id(averaged_data_json).publish_state(json_output); // 清空读数列表,准备下一轮收集 id(sensor_readings).clear(); # 上报JSON到Web服务(替换为你的服务地址) - http_request.post: url: "http://your-web-service/api/collect-data" headers: Content-Type: "application/json" body: !lambda "return id(averaged_data_json).state;"
关键部分说明
- 全局变量:
sensor_readings用std::map<std::string, std::vector<float>>类型,按传感器键存储对应时间段内的所有读数。 - 串口解析:通过
uart组件接收传感器发送的JSON,用json组件解析后存入全局变量。 - 定时任务:每10秒触发一次,遍历全局变量计算平均值(或自定义过滤),生成标准JSON后通过
http_request上报。 - 过滤逻辑扩展:可以替换平均值计算为取最新值、最大值、最小值,甚至实现中位数计算(需额外编写逻辑)。
注意事项
- 若传感器数据量极大,需关注ESP的内存占用,可在lambda中限制每个键的读数列表长度(比如超过1000条时移除最早的记录)。
- 确保Web服务支持POST请求,且能正确解析JSON格式的请求体。
- 调试时可通过Home Assistant或ESPHome Dashboard查看
Averaged Sensor Data文本传感器的输出,验证合并后的JSON格式。
内容的提问来源于stack exchange,提问作者the_smart_home_maker
相关产品推荐
相关产品推荐

