mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 21:44:55 +01:00
web_server: Add cover calls to REST API (#999)
Add the GET and POST handler for cover components. Also add covers to the index page although the Open/Close buttons that are shown for covers will need a few lines added to webserver-v1.js, without them they don't do anything.
This commit is contained in:
parent
8613c02d5c
commit
17fd9d5107
2 changed files with 95 additions and 0 deletions
|
@ -108,6 +108,12 @@ void WebServer::setup() {
|
||||||
if (!obj->is_internal())
|
if (!obj->is_internal())
|
||||||
client->send(this->text_sensor_json(obj, obj->state).c_str(), "state");
|
client->send(this->text_sensor_json(obj, obj->state).c_str(), "state");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
for (auto *obj : App.get_covers())
|
||||||
|
if (!obj->is_internal())
|
||||||
|
client->send(this->cover_json(obj).c_str(), "state");
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef USE_LOGGER
|
#ifdef USE_LOGGER
|
||||||
|
@ -180,6 +186,11 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
||||||
write_row(stream, obj, "text_sensor", "");
|
write_row(stream, obj, "text_sensor", "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
for (auto *obj : App.get_covers())
|
||||||
|
write_row(stream, obj, "cover", "<button>Open</button><button>Close</button>");
|
||||||
|
#endif
|
||||||
|
|
||||||
stream->print(F("</tbody></table><p>See <a href=\"https://esphome.io/web-api/index.html\">ESPHome Web API</a> for "
|
stream->print(F("</tbody></table><p>See <a href=\"https://esphome.io/web-api/index.html\">ESPHome Web API</a> for "
|
||||||
"REST API documentation.</p>"
|
"REST API documentation.</p>"
|
||||||
"<h2>OTA Update</h2><form method=\"POST\" action=\"/update\" enctype=\"multipart/form-data\"><input "
|
"<h2>OTA Update</h2><form method=\"POST\" action=\"/update\" enctype=\"multipart/form-data\"><input "
|
||||||
|
@ -495,6 +506,68 @@ std::string WebServer::light_json(light::LightState *obj) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
void WebServer::on_cover_update(cover::Cover *obj) {
|
||||||
|
if (obj->is_internal())
|
||||||
|
return;
|
||||||
|
this->events_.send(this->cover_json(obj).c_str(), "state");
|
||||||
|
}
|
||||||
|
void WebServer::handle_cover_request(AsyncWebServerRequest *request, UrlMatch match) {
|
||||||
|
for (cover::Cover *obj : App.get_covers()) {
|
||||||
|
if (obj->is_internal())
|
||||||
|
continue;
|
||||||
|
if (obj->get_object_id() != match.id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (request->method() == HTTP_GET) {
|
||||||
|
std::string data = this->cover_json(obj);
|
||||||
|
request->send(200, "text/json", data.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto call = obj->make_call();
|
||||||
|
if (match.method == "open") {
|
||||||
|
call.set_command_open();
|
||||||
|
} else if (match.method == "close") {
|
||||||
|
call.set_command_close();
|
||||||
|
} else if (match.method == "stop") {
|
||||||
|
call.set_command_stop();
|
||||||
|
} else if (match.method != "set") {
|
||||||
|
request->send(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto traits = obj->get_traits();
|
||||||
|
if ((request->hasParam("position") && !traits.get_supports_position()) ||
|
||||||
|
(request->hasParam("tilt") && !traits.get_supports_tilt())) {
|
||||||
|
request->send(409);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->hasParam("position"))
|
||||||
|
call.set_position(request->getParam("position")->value().toFloat());
|
||||||
|
if (request->hasParam("tilt"))
|
||||||
|
call.set_tilt(request->getParam("tilt")->value().toFloat());
|
||||||
|
|
||||||
|
this->defer([call]() mutable { call.perform(); });
|
||||||
|
request->send(200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
request->send(404);
|
||||||
|
}
|
||||||
|
std::string WebServer::cover_json(cover::Cover *obj) {
|
||||||
|
return json::build_json([obj](JsonObject &root) {
|
||||||
|
root["id"] = "cover-" + obj->get_object_id();
|
||||||
|
root["state"] = obj->is_fully_closed() ? "CLOSED" : "OPEN";
|
||||||
|
root["value"] = obj->position;
|
||||||
|
root["current_operation"] = cover::cover_operation_to_str(obj->current_operation);
|
||||||
|
|
||||||
|
if (obj->get_traits().get_supports_tilt())
|
||||||
|
root["tilt"] = obj->tilt;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
||||||
if (request->url() == "/")
|
if (request->url() == "/")
|
||||||
return true;
|
return true;
|
||||||
|
@ -542,6 +615,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "cover")
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
||||||
|
@ -610,6 +688,13 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
if (match.domain == "cover") {
|
||||||
|
this->handle_cover_request(request, match);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebServer::isRequestHandlerTrivial() { return false; }
|
bool WebServer::isRequestHandlerTrivial() { return false; }
|
||||||
|
|
|
@ -144,6 +144,16 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
|
||||||
std::string text_sensor_json(text_sensor::TextSensor *obj, const std::string &value);
|
std::string text_sensor_json(text_sensor::TextSensor *obj, const std::string &value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
void on_cover_update(cover::Cover *obj) override;
|
||||||
|
|
||||||
|
/// Handle a cover request under '/cover/<id>/<open/close/stop/set>'.
|
||||||
|
void handle_cover_request(AsyncWebServerRequest *request, UrlMatch match);
|
||||||
|
|
||||||
|
/// Dump the cover state as a JSON string.
|
||||||
|
std::string cover_json(cover::Cover *obj);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Override the web handler's canHandle method.
|
/// Override the web handler's canHandle method.
|
||||||
bool canHandle(AsyncWebServerRequest *request) override;
|
bool canHandle(AsyncWebServerRequest *request) override;
|
||||||
/// Override the web handler's handleRequest method.
|
/// Override the web handler's handleRequest method.
|
||||||
|
|
Loading…
Reference in a new issue