diff --git a/code/espurna/button.cpp b/code/espurna/button.cpp index 47890e80..a4c7d1bd 100644 --- a/code/espurna/button.cpp +++ b/code/espurna/button.cpp @@ -1144,7 +1144,7 @@ BasePinPtr _buttonGpioPin(size_t index, ButtonProvider provider) { break; } - result = std::move(base->pin(pin)); + result = base->pin(pin); #endif break; } diff --git a/code/espurna/gpio.cpp b/code/espurna/gpio.cpp index 38563b46..887f8e10 100644 --- a/code/espurna/gpio.cpp +++ b/code/espurna/gpio.cpp @@ -153,7 +153,7 @@ BasePinPtr gpioRegister(GpioBase& base, unsigned char gpio) { BasePinPtr result; if (gpioLock(base, gpio)) { - result = std::move(base.pin(gpio)); + result = base.pin(gpio); } return result; diff --git a/code/espurna/light.cpp b/code/espurna/light.cpp index 6483f34f..cbbd687f 100644 --- a/code/espurna/light.cpp +++ b/code/espurna/light.cpp @@ -2408,7 +2408,7 @@ void _lightInitCommands() { } auto description = [&](size_t channel) { - ctx.output.printf("#%u (%s) input:%ld value:%ld target:%ld current:%s\n", + ctx.output.printf_P(PSTR("#%zu (%s) input:%ld value:%ld target:%ld current:%s\n"), channel, _lightDesc(Channels, channel), _light_channels[channel].inputValue, _light_channels[channel].value, diff --git a/code/espurna/relay.cpp b/code/espurna/relay.cpp index 3b2f8d3e..55ea55cb 100644 --- a/code/espurna/relay.cpp +++ b/code/espurna/relay.cpp @@ -712,8 +712,7 @@ void relayOnStatusChange(RelayStatusCallback callback) { namespace { struct GpioProvider : public RelayProviderBase { - GpioProvider(size_t id, RelayType type, std::unique_ptr&& pin, std::unique_ptr&& reset_pin) : - _id(id), + GpioProvider(RelayType type, std::unique_ptr&& pin, std::unique_ptr&& reset_pin) : _type(type), _pin(std::move(pin)), _reset_pin(std::move(reset_pin)) @@ -772,7 +771,6 @@ struct GpioProvider : public RelayProviderBase { } private: - size_t _id { RelaysMax }; RelayType _type { RelayType::Normal }; std::unique_ptr _pin; std::unique_ptr _reset_pin; @@ -1914,7 +1912,7 @@ void _relayMqttSubscribeCustomTopics() { if (key.startsWith(SubPrefix)) { if (_relayTryParseId(key.c_str() + strlen(SubPrefix), id)) { - topics[id] = std::move(kv.value.read()); + topics[id] = kv.value.read(); } } else if (key.startsWith(ModePrefix)) { if (_relayTryParseId(key.c_str() + strlen(ModePrefix), id)) { @@ -2351,7 +2349,7 @@ std::unique_ptr _relayGpioProvider(size_t index, RelayType type) { if (main) { auto reset = gpioRegister(*cfg.base, cfg.reset); return std::make_unique( - index, type, std::move(main), std::move(reset)); + type, std::move(main), std::move(reset)); } return nullptr; diff --git a/code/espurna/settings.cpp b/code/espurna/settings.cpp index 8f3f97eb..7d236b5b 100644 --- a/code/espurna/settings.cpp +++ b/code/espurna/settings.cpp @@ -349,11 +349,11 @@ String getSetting(const SettingsKey& key) { } String getSetting(const SettingsKey& key, const char* defaultValue) { - return getSetting(key, std::move(String(defaultValue))); + return getSetting(key, String(defaultValue)); } String getSetting(const SettingsKey& key, const __FlashStringHelper* defaultValue) { - return getSetting(key, std::move(String(defaultValue))); + return getSetting(key, String(defaultValue)); } String getSetting(const SettingsKey& key, const String& defaultValue) { @@ -506,7 +506,7 @@ void _settingsInitCommands() { terminalRegisterCommand(F("KEYS"), [](const terminal::CommandContext& ctx) { auto keys = settingsKeys(); - ctx.output.printf_P(PSTR("Current settings:")); + ctx.output.print(F("Current settings:")); String value; for (unsigned int i=0; i(value), base); + return serialize(static_cast(value), base); } inline String serialize(int16_t value, int base = 10) { return String(value, base); } +inline String serialize(int32_t value, int base = 10) { + return String(value, base); +} + inline String serialize(int8_t value, int base = 10) { - return serialize(static_cast(value), base); + return serialize(static_cast(value), base); } inline String serialize(long value, int base = 10) { return String(value, base); } -inline String serialize(int value, int base = 10) { - static_assert(sizeof(long) == sizeof(int32_t), ""); - static_assert(sizeof(int) == sizeof(long), ""); - return serialize(static_cast(value), base); -} - inline String serialize(float value) { return String(value, 3); } @@ -178,9 +174,6 @@ void moveSetting(const String& from, const String& to); void moveSetting(const String& from, const String& to, size_t index); void moveSettings(const String& from, const String& to); -template ::type> -T getSetting(const SettingsKey& key, T defaultValue) __attribute__((noinline)); - template ::type> T getSetting(const SettingsKey& key, T defaultValue) { auto result = settings::internal::get(key.value()); @@ -208,7 +201,7 @@ bool setSetting(const SettingsKey& key, T&& value) { template::type> bool setSetting(const SettingsKey& key, T value) { - return setSetting(key, std::move(String(value))); + return setSetting(key, String(value)); } bool delSetting(const char* key); diff --git a/code/espurna/terminal.cpp b/code/espurna/terminal.cpp index d6e9bce8..87f0486a 100644 --- a/code/espurna/terminal.cpp +++ b/code/espurna/terminal.cpp @@ -26,7 +26,7 @@ Copyright (C) 2020 by Maxim Prokhorov #include "libs/StreamAdapter.h" #include "libs/PrintString.h" -#include "web_asyncwebprint_impl.h" +#include "web_asyncwebprint.ipp" #include #include diff --git a/code/espurna/web.cpp b/code/espurna/web.cpp index debce848..694026f4 100644 --- a/code/espurna/web.cpp +++ b/code/espurna/web.cpp @@ -64,17 +64,14 @@ namespace { #include "static/server.key.h" #endif // WEB_SSL_ENABLED -AsyncWebPrint::AsyncWebPrint(const AsyncWebPrintConfig& config, AsyncWebServerRequest* request) : - mimeType(config.mimeType), - backlogCountMax(config.backlogCountMax), - backlogSizeMax(config.backlogSizeMax), - backlogTimeout(config.backlogTimeout), +AsyncWebPrint::AsyncWebPrint(AsyncWebPrintConfig config, AsyncWebServerRequest* request) : + _config(config), _request(request), _state(State::None) {} bool AsyncWebPrint::_addBuffer() { - if ((_buffers.size() + 1) > backlogCountMax) { + if ((_buffers.size() + 1) > _config.backlog.count) { if (!_exhaustBuffers()) { _state = State::Error; return false; @@ -83,7 +80,7 @@ bool AsyncWebPrint::_addBuffer() { // Note: c++17, emplace returns created object reference // c++11, we need to use .back() - _buffers.emplace_back(backlogSizeMax, 0); + _buffers.emplace_back(_config.backlog.size, 0); _buffers.back().clear(); return true; @@ -103,7 +100,7 @@ bool AsyncWebPrint::_addBuffer() { void AsyncWebPrint::_prepareRequest() { _state = State::Sending; - auto *response = _request->beginChunkedResponse(mimeType, [this](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + auto *response = _request->beginChunkedResponse(_config.mimeType, [this](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { switch (_state) { case State::None: return RESPONSE_TRY_AGAIN; @@ -159,9 +156,13 @@ bool AsyncWebPrint::_exhaustBuffers() { _prepareRequest(); } - const auto start = millis(); + constexpr espurna::duration::Seconds Timeout { 5 }; + + using TimeSource = espurna::time::CoreClock; + const auto start = TimeSource::now(); + do { - if (millis() - start > 5000) { + if (TimeSource::now() - start > Timeout) { _buffers.clear(); break; } @@ -275,7 +276,6 @@ void _onGetConfig(AsyncWebServerRequest *request) { auto out = std::make_shared(); out->reserve(TCP_MSS); - char buffer[256]; int prefix_len = snprintf_P(buffer, sizeof(buffer), PSTR("{\n\"app\": \"%s\",\n\"version\": \"%s\",\n\"backup\": \"1\""), diff --git a/code/espurna/web.h b/code/espurna/web.h index e5128961..db8f6f02 100644 --- a/code/espurna/web.h +++ b/code/espurna/web.h @@ -19,14 +19,18 @@ Copyright (C) 2016-2019 by Xose Pérez #include struct AsyncWebPrintConfig { + struct Backlog { + size_t count; + size_t size; + espurna::duration::Seconds timeout; + }; + const char* const mimeType; - size_t backlogCountMax; - size_t backlogSizeMax; - decltype(millis()) backlogTimeout; + Backlog backlog; }; -struct AsyncWebPrint : public Print { - +class AsyncWebPrint : public Print { +public: enum class State { None, Sending, @@ -35,12 +39,13 @@ struct AsyncWebPrint : public Print { }; using BufferType = std::vector; + using TimeSource = espurna::time::CoreClock; // To be able to safely output data right from the request callback, // we schedule a 'printer' task that will print into the request response buffer via AsyncChunkedResponse // Note: implementation must be included in the header template - static void scheduleFromRequest(const AsyncWebPrintConfig& config, AsyncWebServerRequest*, CallbackType); + static void scheduleFromRequest(AsyncWebPrintConfig config, AsyncWebServerRequest*, CallbackType); template static void scheduleFromRequest(AsyncWebServerRequest*, CallbackType); @@ -58,23 +63,18 @@ struct AsyncWebPrint : public Print { size_t write(uint8_t) final override; size_t write(const uint8_t *buffer, size_t size) final override; - const char* const mimeType; - const size_t backlogCountMax; - const size_t backlogSizeMax; - const decltype(millis()) backlogTimeout; - - protected: +protected: + AsyncWebPrintConfig _config; std::list _buffers; AsyncWebServerRequest* const _request; State _state; - AsyncWebPrint(const AsyncWebPrintConfig&, AsyncWebServerRequest* req); + AsyncWebPrint(AsyncWebPrintConfig, AsyncWebServerRequest* req); bool _addBuffer(); bool _exhaustBuffers(); void _prepareRequest(); - }; using web_body_callback_f = std::function; diff --git a/code/espurna/web_asyncwebprint_impl.h b/code/espurna/web_asyncwebprint.ipp similarity index 84% rename from code/espurna/web_asyncwebprint_impl.h rename to code/espurna/web_asyncwebprint.ipp index 6c529df3..c667f5b2 100644 --- a/code/espurna/web_asyncwebprint_impl.h +++ b/code/espurna/web_asyncwebprint.ipp @@ -28,7 +28,7 @@ using is_print_callable = is_detected; } template -void AsyncWebPrint::scheduleFromRequest(const AsyncWebPrintConfig& config, AsyncWebServerRequest* request, CallbackType callback) { +void AsyncWebPrint::scheduleFromRequest(AsyncWebPrintConfig config, AsyncWebServerRequest* request, CallbackType callback) { static_assert(asyncwebprint::traits::is_print_callable::value, "CallbackType needs to be a callable with void(Print&)"); // because of async nature of the server, we need to make sure we outlive 'request' object @@ -55,11 +55,13 @@ void AsyncWebPrint::scheduleFromRequest(const AsyncWebPrintConfig& config, Async }); } -constexpr AsyncWebPrintConfig AsyncWebPrintDefaults { - /*mimeType =*/ "text/plain", - /*backlogCountMax=*/ 2, - /*backlogSizeMax= */ TCP_MSS, - /*backlogTimeout= */ 5000 +static constexpr AsyncWebPrintConfig AsyncWebPrintDefaults { + .mimeType = "text/plain", + .backlog = { + .count = 2, + .size = TCP_MSS, + .timeout = espurna::duration::Seconds(5) + } }; template diff --git a/code/espurna/ws.cpp b/code/espurna/ws.cpp index fb545929..0670e39e 100644 --- a/code/espurna/ws.cpp +++ b/code/espurna/ws.cpp @@ -75,7 +75,7 @@ void EnumerableConfig::operator()(const __FlashStringHelper* name, Iota iota, Ch } } -const char EnumerableConfig::SchemaKey[] PROGMEM = "schema"; +alignas(4) const char EnumerableConfig::SchemaKey[] PROGMEM = "schema"; static_assert(alignof(EnumerableConfig::SchemaKey) == 4, ""); } // namespace ws