Browse Source

web: json adapter for our string view

effectively, same thing as `const __FlashStringHelper*`
but, we know the actual size at build time vs. calling `strlen_P`

can't specialize the way things are read until v6; current implemenation
simply attaches arbitrary char pointer to the internal buffer, which is
then read byte-by-byte when writing output json stream

revert to static json buffer class in `/discovery`
will move more things to it, but probably should move to v6 first
pull/2552/head
Maxim Prokhorov 1 year ago
parent
commit
d32c4b45d0
3 changed files with 91 additions and 25 deletions
  1. +23
    -23
      code/espurna/web.cpp
  2. +2
    -2
      code/espurna/web.h
  3. +66
    -0
      code/espurna/web_utils.h

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

@ -14,12 +14,6 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <functional>
#include <memory>
#include "ntp.h"
#include "settings.h"
#include "system.h"
#include "utils.h"
#include "web.h"
#include <Schedule.h>
#include <Print.h>
#include <Hash.h>
@ -29,6 +23,14 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <ESPAsyncWebServer.h>
#include <AsyncJson.h>
#include "ntp.h"
#include "settings.h"
#include "system.h"
#include "utils.h"
#include "web.h"
#include "web_utils.h"
#if WEB_EMBEDDED
namespace {
@ -304,25 +306,22 @@ void _onReset(AsyncWebServerRequest *request) {
}
void _onDiscover(AsyncWebServerRequest *request) {
const auto app = buildApp();
StaticJsonBuffer<JSON_OBJECT_SIZE(5) + 128> buffer;
JsonObject& root = buffer.createObject();
char buffer[256];
int prefix_len = snprintf_P(buffer, sizeof(buffer),
PSTR("{\"hostname\":\"%s\","
"\"device\":\"%s\","
"\"app\":\"%s\","
"\"version\": \"%s\"}"),
systemHostname().c_str(),
systemDevice().c_str(),
app.name.c_str(),
app.version.c_str());
root["hostname"] = systemHostname();
root["device"] = systemDevice();
if (prefix_len <= 0) {
request->send(500);
return;
}
const auto app = buildApp();
root["app"] = app.name;
root["version"] = app.version;
request->send(200, F("application/json"), buffer);
auto* response = request->beginResponseStream(
F("application/json"), root.measureLength());
response->setCode(200);
root.printTo(*response);
request->send(response);
}
void _onGetConfig(AsyncWebServerRequest *request) {
@ -358,7 +357,8 @@ void _onGetConfig(AsyncWebServerRequest *request) {
});
*out += "\n}";
AsyncWebServerResponse* response = request->beginChunkedResponse("application/json",
AsyncWebServerResponse* response = request->beginChunkedResponse(
F("application/json"),
[out](uint8_t* buffer, size_t maxLen, size_t index) -> size_t {
auto len = out->length();
if (index == len) {


+ 2
- 2
code/espurna/web.h View File

@ -12,12 +12,12 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if WEB_SUPPORT
#include <ESPAsyncWebServer.h>
#include <functional>
#include <list>
#include <vector>
#include <ESPAsyncWebServer.h>
struct AsyncWebPrintConfig {
struct Backlog {
size_t count;


+ 66
- 0
code/espurna/web_utils.h View File

@ -0,0 +1,66 @@
/*
Part of WEBSERVER MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
Copyright (C) 2019-2022 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
*/
#pragma once
#include <ArduinoJson.h>
#include <sys/pgmspace.h>
#include "types.h"
namespace ArduinoJson {
namespace Internals {
// ArduinoJson v5 view adapter; we can't force variant to not
// buffer us until v6, but might as well make it aware of this type
// (internals depend on JsonVariant asString, which works through normal string functions)
template <>
struct StringTraits<::espurna::StringView, void> {
static bool equals(::espurna::StringView lhs, const char* rhs) {
return lhs == rhs;
}
static bool is_null(::espurna::StringView string) {
return string.length() == 0;
}
using duplicate_t = const char*;
template <typename Buffer>
static const char* duplicate(::espurna::StringView string, Buffer* buffer) {
if (string.length()) {
const auto size = string.length();
auto* dup = reinterpret_cast<char*>(buffer->alloc(size));
if (dup) {
memcpy_P(dup, string.begin(), size);
dup[size] = '\0';
return dup;
}
}
return nullptr;
}
static const bool has_append = false;
static const bool has_equals = true;
static const bool should_duplicate = true;
};
template <>
struct ValueSaver<::espurna::StringView> {
template <typename Destination>
static bool save(JsonBuffer*, Destination& dst, ::espurna::StringView src) {
dst = src;
return true;
}
};
} // namespace Internals
} // namespace ArduinoJson

Loading…
Cancel
Save