Browse Source

terminal: make sure API is loaded after the web server

New apiRegister depends on `webServer()` returning a valid object.
mcspr-patch-1
Maxim Prokhorov 3 years ago
parent
commit
9f24e6a325
5 changed files with 72 additions and 74 deletions
  1. +6
    -0
      code/espurna/main.cpp
  2. +1
    -1
      code/espurna/system.cpp
  3. +63
    -72
      code/espurna/terminal.cpp
  4. +1
    -0
      code/espurna/terminal.h
  5. +1
    -1
      code/espurna/web.cpp

+ 6
- 0
code/espurna/main.cpp View File

@ -192,6 +192,12 @@ void setup() {
apiSetup();
#endif
// Run terminal command and send back the result
#if TERMINAL_WEB_API_SUPPORT
terminalWebApiSetup();
#endif
// Special HTTP metrics endpoint
#if PROMETHEUS_SUPPORT
prometheusSetup();
#endif


+ 1
- 1
code/espurna/system.cpp View File

@ -90,7 +90,7 @@ void systemCheck(bool stable) {
if (++value > SYSTEM_CHECK_MAX) {
_systemStable = false;
value = 0;
value = SYSTEM_CHECK_MAX;
DEBUG_MSG_P(PSTR("[MAIN] System UNSTABLE\n"));
}
}


+ 63
- 72
code/espurna/terminal.cpp View File

@ -471,18 +471,77 @@ void _terminalLoop() {
}
#if MQTT_SUPPORT && TERMINAL_MQTT_SUPPORT
void _terminalMqttSetup() {
mqttRegister([](unsigned int type, const char * topic, const char * payload) {
if (type == MQTT_CONNECT_EVENT) {
mqttSubscribe(MQTT_TOPIC_CMD);
return;
}
if (type == MQTT_MESSAGE_EVENT) {
String t = mqttMagnitude((char *) topic);
if (!t.startsWith(MQTT_TOPIC_CMD)) return;
if (!strlen(payload)) return;
String cmd(payload);
if (!cmd.endsWith("\r\n") && !cmd.endsWith("\n")) {
cmd += '\n';
}
// TODO: unlike http handler, we have only one output stream
// and **must** have a fixed-size output buffer
// (wishlist: MQTT client does some magic and we don't buffer twice)
schedule_function([cmd]() {
PrintString buffer(TCP_MSS);
StreamAdapter<const char*> stream(buffer, cmd.c_str(), cmd.c_str() + cmd.length() + 1);
String out;
terminal::Terminal handler(stream);
switch (handler.processLine()) {
case terminal::Terminal::Result::CommandNotFound:
out += F("Command not found");
break;
case terminal::Terminal::Result::Command:
out = std::move(buffer);
default:
break;
}
if (out.length()) {
mqttSendRaw(mqttTopic(MQTT_TOPIC_CMD, false).c_str(), out.c_str(), false);
}
});
return;
}
});
}
#endif // MQTT_SUPPORT && TERMINAL_MQTT_SUPPORT
} // namespace
// -----------------------------------------------------------------------------
// Pubic API
// -----------------------------------------------------------------------------
#if TERMINAL_WEB_API_SUPPORT
void _terminalWebApiSetup() {
// XXX: new `apiRegister()` depends that `webServer()` is available, meaning we can't call this setup func
// before the `webSetup()` is called. ATM, just make sure it is in order.
void terminalWebApiSetup() {
#if API_SUPPORT
apiRegister(getSetting("termWebApiPath", TERMINAL_WEB_API_PATH),
[](ApiRequest& api) {
api.handle([](AsyncWebServerRequest* request) {
AsyncResponseStream *response = request->beginResponseStream("text/plain");
for (auto& command : _terminal.commandNames()) {
response->print(command);
for (auto* name : _terminal.names()) {
response->print(name);
response->print("\r\n");
}
@ -513,9 +572,7 @@ void _terminalWebApiSetup() {
return true;
}
);
#else
webRequestRegister([](AsyncWebServerRequest* request) {
String path(F(API_BASE_PATH));
path += getSetting("termWebApiPath", TERMINAL_WEB_API_PATH);
@ -553,72 +610,11 @@ void _terminalWebApiSetup() {
return true;
});
#endif // API_SUPPORT
}
#endif // TERMINAL_WEB_API_SUPPORT
#if MQTT_SUPPORT && TERMINAL_MQTT_SUPPORT
void _terminalMqttSetup() {
mqttRegister([](unsigned int type, const char * topic, const char * payload) {
if (type == MQTT_CONNECT_EVENT) {
mqttSubscribe(MQTT_TOPIC_CMD);
return;
}
if (type == MQTT_MESSAGE_EVENT) {
String t = mqttMagnitude((char *) topic);
if (!t.startsWith(MQTT_TOPIC_CMD)) return;
if (!strlen(payload)) return;
String cmd(payload);
if (!cmd.endsWith("\r\n") && !cmd.endsWith("\n")) {
cmd += '\n';
}
// TODO: unlike http handler, we have only one output stream
// and **must** have a fixed-size output buffer
// (wishlist: MQTT client does some magic and we don't buffer twice)
schedule_function([cmd]() {
PrintString buffer(TCP_MSS);
StreamAdapter<const char*> stream(buffer, cmd.c_str(), cmd.c_str() + cmd.length() + 1);
String out;
terminal::Terminal handler(stream);
switch (handler.processLine()) {
case terminal::Terminal::Result::CommandNotFound:
out += F("Command not found");
break;
case terminal::Terminal::Result::Command:
out = std::move(buffer);
default:
break;
}
if (out.length()) {
mqttSendRaw(mqttTopic(MQTT_TOPIC_CMD, false).c_str(), out.c_str(), false);
}
});
return;
}
});
}
#endif // MQTT_SUPPORT && TERMINAL_MQTT_SUPPORT
}
// -----------------------------------------------------------------------------
// Pubic API
// -----------------------------------------------------------------------------
Stream & terminalDefaultStream() {
return (Stream &) _io;
}
@ -671,11 +667,6 @@ void terminalSetup() {
.onVisible([](JsonObject& root) { root["cmdVisible"] = 1; });
#endif
// Run terminal command and send back the result. Depends on the terminal command using ctx.output
#if WEB_SUPPORT && TERMINAL_WEB_API_SUPPORT
_terminalWebApiSetup();
#endif
// Similar to the above, but we allow only very small and in-place outputs.
#if MQTT_SUPPORT && TERMINAL_MQTT_SUPPORT
_terminalMqttSetup();


+ 1
- 0
code/espurna/terminal.h View File

@ -37,5 +37,6 @@ void terminalInject(char ch);
Stream& terminalDefaultStream();
void terminalSetup();
void terminalWebApiSetup();
#endif // TERMINAL_SUPPORT == 1

+ 1
- 1
code/espurna/web.cpp View File

@ -203,7 +203,7 @@ size_t AsyncWebPrint::write(const uint8_t* data, size_t size) {
// -----------------------------------------------------------------------------
AsyncWebServer * _server;
AsyncWebServer* _server;
char _last_modified[50];
std::vector<uint8_t> * _webConfigBuffer;
bool _webConfigSuccess = false;


Loading…
Cancel
Save