diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp
index 4cc77da256..7413af67c4 100644
--- a/esphome/components/web_server/web_server.cpp
+++ b/esphome/components/web_server/web_server.cpp
@@ -236,7 +236,18 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
#ifdef USE_NUMBER
for (auto *obj : App.get_numbers())
if (this->include_internal_ || !obj->is_internal())
- write_row(stream, obj, "number", "");
+ write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) {
+ number::Number *number = (number::Number *) obj;
+ stream.print(R"(traits.get_min_value());
+ stream.print(R"(" max=")");
+ stream.print(number->traits.get_max_value());
+ stream.print(R"(" step=")");
+ stream.print(number->traits.get_step());
+ stream.print(R"(" value=")");
+ stream.print(number->state);
+ stream.print(R"("/>)");
+ });
#endif
#ifdef USE_SELECT
@@ -652,8 +663,29 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
for (auto *obj : App.get_numbers()) {
if (obj->get_object_id() != match.id)
continue;
- std::string data = this->number_json(obj, obj->state);
- request->send(200, "text/json", data.c_str());
+
+ if (request->method() == HTTP_GET) {
+ std::string data = this->number_json(obj, obj->state);
+ request->send(200, "text/json", data.c_str());
+ return;
+ }
+
+ if (match.method != "set") {
+ request->send(404);
+ return;
+ }
+
+ auto call = obj->make_call();
+
+ if (request->hasParam("value")) {
+ String value = request->getParam("value")->value();
+ optional value_f = parse_number(value.c_str());
+ if (value_f.has_value())
+ call.set_value(*value_f);
+ }
+
+ this->defer([call]() mutable { call.perform(); });
+ request->send(200);
return;
}
request->send(404);
@@ -661,9 +693,8 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
std::string WebServer::number_json(number::Number *obj, float value) {
return json::build_json([obj, value](JsonObject root) {
root["id"] = "number-" + obj->get_object_id();
- char buffer[64];
- snprintf(buffer, sizeof(buffer), "%f", value);
- root["state"] = buffer;
+ std::string state = str_sprintf("%f", value);
+ root["state"] = state;
root["value"] = value;
});
}
@@ -769,7 +800,7 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
#endif
#ifdef USE_NUMBER
- if (request->method() == HTTP_GET && match.domain == "number")
+ if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "number")
return true;
#endif