mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
Upgrade ArduinoJson to 6.18.5 and migrate code (#2844)
This commit is contained in:
parent
23edb18d7e
commit
33f17f75a0
40 changed files with 126 additions and 231 deletions
|
@ -75,8 +75,7 @@ from esphome.cpp_types import ( # noqa
|
||||||
optional,
|
optional,
|
||||||
arduino_json_ns,
|
arduino_json_ns,
|
||||||
JsonObject,
|
JsonObject,
|
||||||
JsonObjectRef,
|
JsonObjectConst,
|
||||||
JsonObjectConstRef,
|
|
||||||
Controller,
|
Controller,
|
||||||
GPIOPin,
|
GPIOPin,
|
||||||
InternalGPIOPin,
|
InternalGPIOPin,
|
||||||
|
|
|
@ -172,7 +172,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args):
|
||||||
if CONF_JSON in config:
|
if CONF_JSON in config:
|
||||||
json_ = config[CONF_JSON]
|
json_ = config[CONF_JSON]
|
||||||
if isinstance(json_, Lambda):
|
if isinstance(json_, Lambda):
|
||||||
args_ = args + [(cg.JsonObjectRef, "root")]
|
args_ = args + [(cg.JsonObject, "root")]
|
||||||
lambda_ = await cg.process_lambda(json_, args_, return_type=cg.void)
|
lambda_ = await cg.process_lambda(json_, args_, return_type=cg.void)
|
||||||
cg.add(var.set_json(lambda_))
|
cg.add(var.set_json(lambda_))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -78,7 +78,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||||
|
|
||||||
void add_json(const char *key, TemplatableValue<std::string, Ts...> value) { this->json_.insert({key, value}); }
|
void add_json(const char *key, TemplatableValue<std::string, Ts...> value) { this->json_.insert({key, value}); }
|
||||||
|
|
||||||
void set_json(std::function<void(Ts..., JsonObject &)> json_func) { this->json_func_ = json_func; }
|
void set_json(std::function<void(Ts..., JsonObject)> json_func) { this->json_func_ = json_func; }
|
||||||
|
|
||||||
void register_response_trigger(HttpRequestResponseTrigger *trigger) { this->response_triggers_.push_back(trigger); }
|
void register_response_trigger(HttpRequestResponseTrigger *trigger) { this->response_triggers_.push_back(trigger); }
|
||||||
|
|
||||||
|
@ -118,17 +118,17 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void encode_json_(Ts... x, JsonObject &root) {
|
void encode_json_(Ts... x, JsonObject root) {
|
||||||
for (const auto &item : this->json_) {
|
for (const auto &item : this->json_) {
|
||||||
auto val = item.second;
|
auto val = item.second;
|
||||||
root[item.first] = val.value(x...);
|
root[item.first] = val.value(x...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void encode_json_func_(Ts... x, JsonObject &root) { this->json_func_(x..., root); }
|
void encode_json_func_(Ts... x, JsonObject root) { this->json_func_(x..., root); }
|
||||||
HttpRequestComponent *parent_;
|
HttpRequestComponent *parent_;
|
||||||
std::map<const char *, TemplatableValue<const char *, Ts...>> headers_{};
|
std::map<const char *, TemplatableValue<const char *, Ts...>> headers_{};
|
||||||
std::map<const char *, TemplatableValue<std::string, Ts...>> json_{};
|
std::map<const char *, TemplatableValue<std::string, Ts...>> json_{};
|
||||||
std::function<void(Ts..., JsonObject &)> json_func_{nullptr};
|
std::function<void(Ts..., JsonObject)> json_func_{nullptr};
|
||||||
std::vector<HttpRequestResponseTrigger *> response_triggers_;
|
std::vector<HttpRequestResponseTrigger *> response_triggers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,11 @@ json_ns = cg.esphome_ns.namespace("json")
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
cv.Schema({}),
|
cv.Schema({}),
|
||||||
cv.only_with_arduino,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@coroutine_with_priority(1.0)
|
@coroutine_with_priority(1.0)
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add_library("ottowinter/ArduinoJson-esphomelib", "5.13.3")
|
cg.add_library("bblanchon/ArduinoJson", "6.18.5")
|
||||||
cg.add_define("USE_JSON")
|
cg.add_define("USE_JSON")
|
||||||
cg.add_global(json_ns.using)
|
cg.add_global(json_ns.using)
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
|
|
||||||
#include "json_util.h"
|
#include "json_util.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP8266
|
||||||
|
#include <Esp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
|
@ -10,110 +12,49 @@ static const char *const TAG = "json";
|
||||||
|
|
||||||
static std::vector<char> global_json_build_buffer; // NOLINT
|
static std::vector<char> global_json_build_buffer; // NOLINT
|
||||||
|
|
||||||
const char *build_json(const json_build_t &f, size_t *length) {
|
std::string build_json(const json_build_t &f) {
|
||||||
global_json_buffer.clear();
|
// Here we are allocating as much heap memory as available minus 2kb to be safe
|
||||||
JsonObject &root = global_json_buffer.createObject();
|
// as we can not have a true dynamic sized document.
|
||||||
|
// The excess memory is freed below with `shrinkToFit()`
|
||||||
|
#ifdef USE_ESP8266
|
||||||
|
const size_t free_heap = ESP.getMaxFreeBlockSize() - 2048; // NOLINT(readability-static-accessed-through-instance)
|
||||||
|
#elif defined(USE_ESP32)
|
||||||
|
const size_t free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT) - 2048;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DynamicJsonDocument json_document(free_heap);
|
||||||
|
JsonObject root = json_document.to<JsonObject>();
|
||||||
f(root);
|
f(root);
|
||||||
|
json_document.shrinkToFit();
|
||||||
|
|
||||||
// The Json buffer size gives us a good estimate for the required size.
|
std::string output;
|
||||||
// Usually, it's a bit larger than the actual required string size
|
serializeJson(json_document, output);
|
||||||
// | JSON Buffer Size | String Size |
|
return output;
|
||||||
// Discovery | 388 | 351 |
|
|
||||||
// Discovery | 372 | 356 |
|
|
||||||
// Discovery | 336 | 311 |
|
|
||||||
// Discovery | 408 | 393 |
|
|
||||||
global_json_build_buffer.reserve(global_json_buffer.size() + 1);
|
|
||||||
size_t bytes_written = root.printTo(global_json_build_buffer.data(), global_json_build_buffer.capacity());
|
|
||||||
|
|
||||||
if (bytes_written >= global_json_build_buffer.capacity() - 1) {
|
|
||||||
global_json_build_buffer.reserve(root.measureLength() + 1);
|
|
||||||
bytes_written = root.printTo(global_json_build_buffer.data(), global_json_build_buffer.capacity());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*length = bytes_written;
|
|
||||||
return global_json_build_buffer.data();
|
|
||||||
}
|
|
||||||
void parse_json(const std::string &data, const json_parse_t &f) {
|
void parse_json(const std::string &data, const json_parse_t &f) {
|
||||||
global_json_buffer.clear();
|
// Here we are allocating as much heap memory as available minus 2kb to be safe
|
||||||
JsonObject &root = global_json_buffer.parseObject(data);
|
// as we can not have a true dynamic sized document.
|
||||||
|
// The excess memory is freed below with `shrinkToFit()`
|
||||||
|
#ifdef USE_ESP8266
|
||||||
|
const size_t free_heap = ESP.getMaxFreeBlockSize() - 2048; // NOLINT(readability-static-accessed-through-instance)
|
||||||
|
#elif defined(USE_ESP32)
|
||||||
|
const size_t free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT) - 2048;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!root.success()) {
|
DynamicJsonDocument json_document(free_heap);
|
||||||
|
DeserializationError err = deserializeJson(json_document, data);
|
||||||
|
json_document.shrinkToFit();
|
||||||
|
|
||||||
|
JsonObject root = json_document.as<JsonObject>();
|
||||||
|
|
||||||
|
if (err) {
|
||||||
ESP_LOGW(TAG, "Parsing JSON failed.");
|
ESP_LOGW(TAG, "Parsing JSON failed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
f(root);
|
f(root);
|
||||||
}
|
}
|
||||||
std::string build_json(const json_build_t &f) {
|
|
||||||
size_t len;
|
|
||||||
const char *c_str = build_json(f, &len);
|
|
||||||
return std::string(c_str, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorJsonBuffer::String::String(VectorJsonBuffer *parent) : parent_(parent), start_(parent->size_) {}
|
|
||||||
void VectorJsonBuffer::String::append(char c) const {
|
|
||||||
char *last = static_cast<char *>(this->parent_->do_alloc(1));
|
|
||||||
*last = c;
|
|
||||||
}
|
|
||||||
const char *VectorJsonBuffer::String::c_str() const {
|
|
||||||
this->append('\0');
|
|
||||||
return &this->parent_->buffer_[this->start_];
|
|
||||||
}
|
|
||||||
void VectorJsonBuffer::clear() {
|
|
||||||
for (char *block : this->free_blocks_)
|
|
||||||
free(block); // NOLINT
|
|
||||||
|
|
||||||
this->size_ = 0;
|
|
||||||
this->free_blocks_.clear();
|
|
||||||
}
|
|
||||||
VectorJsonBuffer::String VectorJsonBuffer::startString() { return {this}; } // NOLINT
|
|
||||||
void *VectorJsonBuffer::alloc(size_t bytes) {
|
|
||||||
// Make sure memory addresses are aligned
|
|
||||||
uint32_t new_size = round_size_up(this->size_);
|
|
||||||
this->resize(new_size);
|
|
||||||
return this->do_alloc(bytes);
|
|
||||||
}
|
|
||||||
void *VectorJsonBuffer::do_alloc(size_t bytes) { // NOLINT
|
|
||||||
const uint32_t begin = this->size_;
|
|
||||||
this->resize(begin + bytes);
|
|
||||||
return &this->buffer_[begin];
|
|
||||||
}
|
|
||||||
void VectorJsonBuffer::resize(size_t size) { // NOLINT
|
|
||||||
if (size <= this->size_) {
|
|
||||||
this->size_ = size;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->reserve(size);
|
|
||||||
this->size_ = size;
|
|
||||||
}
|
|
||||||
void VectorJsonBuffer::reserve(size_t size) { // NOLINT
|
|
||||||
if (size <= this->capacity_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t target_capacity = this->capacity_;
|
|
||||||
if (this->capacity_ == 0) {
|
|
||||||
// lazily initialize with a reasonable size
|
|
||||||
target_capacity = JSON_OBJECT_SIZE(16);
|
|
||||||
}
|
|
||||||
while (target_capacity < size)
|
|
||||||
target_capacity *= 2;
|
|
||||||
|
|
||||||
char *old_buffer = this->buffer_;
|
|
||||||
this->buffer_ = new char[target_capacity]; // NOLINT
|
|
||||||
if (old_buffer != nullptr && this->capacity_ != 0) {
|
|
||||||
this->free_blocks_.push_back(old_buffer);
|
|
||||||
memcpy(this->buffer_, old_buffer, this->capacity_);
|
|
||||||
}
|
|
||||||
this->capacity_ = target_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VectorJsonBuffer::size() const { return this->size_; }
|
|
||||||
|
|
||||||
VectorJsonBuffer global_json_buffer; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
|
||||||
|
|
||||||
} // namespace json
|
} // namespace json
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ARDUINO
|
|
||||||
|
|
|
@ -1,68 +1,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
#undef ARDUINOJSON_ENABLE_STD_STRING
|
||||||
|
#define ARDUINOJSON_ENABLE_STD_STRING 1 // NOLINT
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
/// Callback function typedef for parsing JsonObjects.
|
/// Callback function typedef for parsing JsonObjects.
|
||||||
using json_parse_t = std::function<void(JsonObject &)>;
|
using json_parse_t = std::function<void(JsonObject)>;
|
||||||
|
|
||||||
/// Callback function typedef for building JsonObjects.
|
/// Callback function typedef for building JsonObjects.
|
||||||
using json_build_t = std::function<void(JsonObject &)>;
|
using json_build_t = std::function<void(JsonObject)>;
|
||||||
|
|
||||||
/// Build a JSON string with the provided json build function.
|
/// Build a JSON string with the provided json build function.
|
||||||
const char *build_json(const json_build_t &f, size_t *length);
|
|
||||||
|
|
||||||
std::string build_json(const json_build_t &f);
|
std::string build_json(const json_build_t &f);
|
||||||
|
|
||||||
/// Parse a JSON string and run the provided json parse function if it's valid.
|
/// Parse a JSON string and run the provided json parse function if it's valid.
|
||||||
void parse_json(const std::string &data, const json_parse_t &f);
|
void parse_json(const std::string &data, const json_parse_t &f);
|
||||||
|
|
||||||
class VectorJsonBuffer : public ArduinoJson::Internals::JsonBufferBase<VectorJsonBuffer> {
|
|
||||||
public:
|
|
||||||
class String {
|
|
||||||
public:
|
|
||||||
String(VectorJsonBuffer *parent);
|
|
||||||
|
|
||||||
void append(char c) const;
|
|
||||||
|
|
||||||
const char *c_str() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
VectorJsonBuffer *parent_;
|
|
||||||
uint32_t start_;
|
|
||||||
};
|
|
||||||
|
|
||||||
void *alloc(size_t bytes) override;
|
|
||||||
|
|
||||||
size_t size() const;
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
String startString(); // NOLINT
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void *do_alloc(size_t bytes); // NOLINT
|
|
||||||
|
|
||||||
void resize(size_t size); // NOLINT
|
|
||||||
|
|
||||||
void reserve(size_t size); // NOLINT
|
|
||||||
|
|
||||||
char *buffer_{nullptr};
|
|
||||||
size_t size_{0};
|
|
||||||
size_t capacity_{0};
|
|
||||||
std::vector<char *> free_blocks_;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern VectorJsonBuffer global_json_buffer; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
|
||||||
|
|
||||||
} // namespace json
|
} // namespace json
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ARDUINO
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace light {
|
||||||
|
|
||||||
// See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema
|
// See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema
|
||||||
|
|
||||||
void LightJSONSchema::dump_json(LightState &state, JsonObject &root) {
|
void LightJSONSchema::dump_json(LightState &state, JsonObject root) {
|
||||||
if (state.supports_effects())
|
if (state.supports_effects())
|
||||||
root["effect"] = state.get_effect_name();
|
root["effect"] = state.get_effect_name();
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject &root) {
|
||||||
if (values.get_color_mode() & ColorCapability::BRIGHTNESS)
|
if (values.get_color_mode() & ColorCapability::BRIGHTNESS)
|
||||||
root["brightness"] = uint8_t(values.get_brightness() * 255);
|
root["brightness"] = uint8_t(values.get_brightness() * 255);
|
||||||
|
|
||||||
JsonObject &color = root.createNestedObject("color");
|
JsonObject color = root.createNestedObject("color");
|
||||||
if (values.get_color_mode() & ColorCapability::RGB) {
|
if (values.get_color_mode() & ColorCapability::RGB) {
|
||||||
color["r"] = uint8_t(values.get_color_brightness() * values.get_red() * 255);
|
color["r"] = uint8_t(values.get_color_brightness() * values.get_red() * 255);
|
||||||
color["g"] = uint8_t(values.get_color_brightness() * values.get_green() * 255);
|
color["g"] = uint8_t(values.get_color_brightness() * values.get_green() * 255);
|
||||||
|
@ -72,7 +72,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject &root) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonObject &root) {
|
void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonObject root) {
|
||||||
if (root.containsKey("state")) {
|
if (root.containsKey("state")) {
|
||||||
auto val = parse_on_off(root["state"]);
|
auto val = parse_on_off(root["state"]);
|
||||||
switch (val) {
|
switch (val) {
|
||||||
|
@ -95,7 +95,7 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.containsKey("color")) {
|
if (root.containsKey("color")) {
|
||||||
JsonObject &color = root["color"];
|
JsonObject color = root["color"];
|
||||||
// HA also encodes brightness information in the r, g, b values, so extract that and set it as color brightness.
|
// HA also encodes brightness information in the r, g, b values, so extract that and set it as color brightness.
|
||||||
float max_rgb = 0.0f;
|
float max_rgb = 0.0f;
|
||||||
if (color.containsKey("r")) {
|
if (color.containsKey("r")) {
|
||||||
|
@ -140,7 +140,7 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightJSONSchema::parse_json(LightState &state, LightCall &call, JsonObject &root) {
|
void LightJSONSchema::parse_json(LightState &state, LightCall &call, JsonObject root) {
|
||||||
LightJSONSchema::parse_color_json(state, call, root);
|
LightJSONSchema::parse_color_json(state, call, root);
|
||||||
|
|
||||||
if (root.containsKey("flash")) {
|
if (root.containsKey("flash")) {
|
||||||
|
|
|
@ -14,12 +14,12 @@ namespace light {
|
||||||
class LightJSONSchema {
|
class LightJSONSchema {
|
||||||
public:
|
public:
|
||||||
/// Dump the state of a light as JSON.
|
/// Dump the state of a light as JSON.
|
||||||
static void dump_json(LightState &state, JsonObject &root);
|
static void dump_json(LightState &state, JsonObject root);
|
||||||
/// Parse the JSON state of a light to a LightCall.
|
/// Parse the JSON state of a light to a LightCall.
|
||||||
static void parse_json(LightState &state, LightCall &call, JsonObject &root);
|
static void parse_json(LightState &state, LightCall &call, JsonObject root);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void parse_color_json(LightState &state, LightCall &call, JsonObject &root);
|
static void parse_color_json(LightState &state, LightCall &call, JsonObject root);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace light
|
} // namespace light
|
||||||
|
|
|
@ -80,7 +80,7 @@ MQTTMessageTrigger = mqtt_ns.class_(
|
||||||
"MQTTMessageTrigger", automation.Trigger.template(cg.std_string), cg.Component
|
"MQTTMessageTrigger", automation.Trigger.template(cg.std_string), cg.Component
|
||||||
)
|
)
|
||||||
MQTTJsonMessageTrigger = mqtt_ns.class_(
|
MQTTJsonMessageTrigger = mqtt_ns.class_(
|
||||||
"MQTTJsonMessageTrigger", automation.Trigger.template(cg.JsonObjectConstRef)
|
"MQTTJsonMessageTrigger", automation.Trigger.template(cg.JsonObjectConst)
|
||||||
)
|
)
|
||||||
MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component)
|
MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component)
|
||||||
MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition)
|
MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition)
|
||||||
|
@ -311,7 +311,7 @@ async def to_code(config):
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_JSON_MESSAGE, []):
|
for conf in config.get(CONF_ON_JSON_MESSAGE, []):
|
||||||
trig = cg.new_Pvariable(conf[CONF_TRIGGER_ID], conf[CONF_TOPIC], conf[CONF_QOS])
|
trig = cg.new_Pvariable(conf[CONF_TRIGGER_ID], conf[CONF_TOPIC], conf[CONF_QOS])
|
||||||
await automation.build_automation(trig, [(cg.JsonObjectConstRef, "x")], conf)
|
await automation.build_automation(trig, [(cg.JsonObjectConst, "x")], conf)
|
||||||
|
|
||||||
|
|
||||||
MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
|
MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
|
||||||
|
@ -363,7 +363,7 @@ async def mqtt_publish_json_action_to_code(config, action_id, template_arg, args
|
||||||
template_ = await cg.templatable(config[CONF_TOPIC], args, cg.std_string)
|
template_ = await cg.templatable(config[CONF_TOPIC], args, cg.std_string)
|
||||||
cg.add(var.set_topic(template_))
|
cg.add(var.set_topic(template_))
|
||||||
|
|
||||||
args_ = args + [(cg.JsonObjectRef, "root")]
|
args_ = args + [(cg.JsonObject, "root")]
|
||||||
lambda_ = await cg.process_lambda(config[CONF_PAYLOAD], args_, return_type=cg.void)
|
lambda_ = await cg.process_lambda(config[CONF_PAYLOAD], args_, return_type=cg.void)
|
||||||
cg.add(var.set_payload(lambda_))
|
cg.add(var.set_payload(lambda_))
|
||||||
template_ = await cg.templatable(config[CONF_QOS], args, cg.uint8)
|
template_ = await cg.templatable(config[CONF_QOS], args, cg.uint8)
|
||||||
|
|
|
@ -74,9 +74,9 @@ class CustomMQTTDevice {
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* // topic parameter can be remove if not needed:
|
* // topic parameter can be remove if not needed:
|
||||||
* // e.g.: void on_json_message(JsonObject &payload) {
|
* // e.g.: void on_json_message(JsonObject payload) {
|
||||||
*
|
*
|
||||||
* void on_json_message(const std::string &topic, JsonObject &payload) {
|
* void on_json_message(const std::string &topic, JsonObject payload) {
|
||||||
* // do something with topic and payload
|
* // do something with topic and payload
|
||||||
* if (payload["number"] == 1) {
|
* if (payload["number"] == 1) {
|
||||||
* digitalWrite(5, HIGH);
|
* digitalWrite(5, HIGH);
|
||||||
|
@ -93,11 +93,9 @@ class CustomMQTTDevice {
|
||||||
* @param qos The Quality of Service to subscribe with. Defaults to 0.
|
* @param qos The Quality of Service to subscribe with. Defaults to 0.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void subscribe_json(const std::string &topic, void (T::*callback)(const std::string &, JsonObject &),
|
void subscribe_json(const std::string &topic, void (T::*callback)(const std::string &, JsonObject), uint8_t qos = 0);
|
||||||
uint8_t qos = 0);
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> void subscribe_json(const std::string &topic, void (T::*callback)(JsonObject), uint8_t qos = 0);
|
||||||
void subscribe_json(const std::string &topic, void (T::*callback)(JsonObject &), uint8_t qos = 0);
|
|
||||||
|
|
||||||
/** Publish an MQTT message with the given payload and QoS and retain settings.
|
/** Publish an MQTT message with the given payload and QoS and retain settings.
|
||||||
*
|
*
|
||||||
|
@ -155,7 +153,7 @@ class CustomMQTTDevice {
|
||||||
*
|
*
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* void in_some_method() {
|
* void in_some_method() {
|
||||||
* publish("the/topic", [=](JsonObject &root) {
|
* publish("the/topic", [=](JsonObject root) {
|
||||||
* root["the_key"] = "Hello World!";
|
* root["the_key"] = "Hello World!";
|
||||||
* }, 0, false);
|
* }, 0, false);
|
||||||
* }
|
* }
|
||||||
|
@ -174,7 +172,7 @@ class CustomMQTTDevice {
|
||||||
*
|
*
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* void in_some_method() {
|
* void in_some_method() {
|
||||||
* publish("the/topic", [=](JsonObject &root) {
|
* publish("the/topic", [=](JsonObject root) {
|
||||||
* root["the_key"] = "Hello World!";
|
* root["the_key"] = "Hello World!";
|
||||||
* });
|
* });
|
||||||
* }
|
* }
|
||||||
|
@ -205,13 +203,13 @@ template<typename T> void CustomMQTTDevice::subscribe(const std::string &topic,
|
||||||
global_mqtt_client->subscribe(topic, f, qos);
|
global_mqtt_client->subscribe(topic, f, qos);
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void CustomMQTTDevice::subscribe_json(const std::string &topic, void (T::*callback)(const std::string &, JsonObject &),
|
void CustomMQTTDevice::subscribe_json(const std::string &topic, void (T::*callback)(const std::string &, JsonObject),
|
||||||
uint8_t qos) {
|
uint8_t qos) {
|
||||||
auto f = std::bind(callback, (T *) this, std::placeholders::_1, std::placeholders::_2);
|
auto f = std::bind(callback, (T *) this, std::placeholders::_1, std::placeholders::_2);
|
||||||
global_mqtt_client->subscribe_json(topic, f, qos);
|
global_mqtt_client->subscribe_json(topic, f, qos);
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void CustomMQTTDevice::subscribe_json(const std::string &topic, void (T::*callback)(JsonObject &), uint8_t qos) {
|
void CustomMQTTDevice::subscribe_json(const std::string &topic, void (T::*callback)(JsonObject), uint8_t qos) {
|
||||||
auto f = std::bind(callback, (T *) this, std::placeholders::_2);
|
auto f = std::bind(callback, (T *) this, std::placeholders::_2);
|
||||||
global_mqtt_client->subscribe_json(topic, f, qos);
|
global_mqtt_client->subscribe_json(topic, f, qos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ MQTTBinarySensorComponent::MQTTBinarySensorComponent(binary_sensor::BinarySensor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MQTTBinarySensorComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTBinarySensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
if (!this->binary_sensor_->get_device_class().empty())
|
if (!this->binary_sensor_->get_device_class().empty())
|
||||||
root[MQTT_DEVICE_CLASS] = this->binary_sensor_->get_device_class();
|
root[MQTT_DEVICE_CLASS] = this->binary_sensor_->get_device_class();
|
||||||
if (this->binary_sensor_->is_status_binary_sensor())
|
if (this->binary_sensor_->is_status_binary_sensor())
|
||||||
|
|
|
@ -22,7 +22,7 @@ class MQTTBinarySensorComponent : public mqtt::MQTTComponent {
|
||||||
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
void set_is_status(bool status);
|
void set_is_status(bool status);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ void MQTTButtonComponent::dump_config() {
|
||||||
LOG_MQTT_COMPONENT(true, true);
|
LOG_MQTT_COMPONENT(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MQTTButtonComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTButtonComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
config.state_topic = false;
|
config.state_topic = false;
|
||||||
if (!this->button_->get_device_class().empty())
|
if (!this->button_->get_device_class().empty())
|
||||||
root[MQTT_DEVICE_CLASS] = this->button_->get_device_class();
|
root[MQTT_DEVICE_CLASS] = this->button_->get_device_class();
|
||||||
|
|
|
@ -23,7 +23,7 @@ class MQTTButtonComponent : public mqtt::MQTTComponent {
|
||||||
/// Buttons do not send a state so just return true.
|
/// Buttons do not send a state so just return true.
|
||||||
bool send_initial_state() override { return true; }
|
bool send_initial_state() override { return true; }
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// "button" component type.
|
/// "button" component type.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "mqtt_client.h"
|
#include "mqtt_client.h"
|
||||||
|
#define USE_MQTT
|
||||||
|
|
||||||
#ifdef USE_MQTT
|
#ifdef USE_MQTT
|
||||||
|
|
||||||
|
@ -346,7 +347,7 @@ void MQTTClientComponent::subscribe(const std::string &topic, mqtt_callback_t ca
|
||||||
|
|
||||||
void MQTTClientComponent::subscribe_json(const std::string &topic, const mqtt_json_callback_t &callback, uint8_t qos) {
|
void MQTTClientComponent::subscribe_json(const std::string &topic, const mqtt_json_callback_t &callback, uint8_t qos) {
|
||||||
auto f = [callback](const std::string &topic, const std::string &payload) {
|
auto f = [callback](const std::string &topic, const std::string &payload) {
|
||||||
json::parse_json(payload, [topic, callback](JsonObject &root) { callback(topic, root); });
|
json::parse_json(payload, [topic, callback](JsonObject root) { callback(topic, root); });
|
||||||
};
|
};
|
||||||
MQTTSubscription subscription{
|
MQTTSubscription subscription{
|
||||||
.topic = topic,
|
.topic = topic,
|
||||||
|
@ -416,9 +417,8 @@ bool MQTTClientComponent::publish(const MQTTMessage &message) {
|
||||||
}
|
}
|
||||||
bool MQTTClientComponent::publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos,
|
bool MQTTClientComponent::publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos,
|
||||||
bool retain) {
|
bool retain) {
|
||||||
size_t len;
|
std::string message = json::build_json(f);
|
||||||
const char *message = json::build_json(f, &len);
|
return this->publish(topic, message, qos, retain);
|
||||||
return this->publish(topic, message, len, qos, retain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if the message topic matches the given subscription topic
|
/** Check if the message topic matches the given subscription topic
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace mqtt {
|
||||||
* First parameter is the topic, the second one is the payload.
|
* First parameter is the topic, the second one is the payload.
|
||||||
*/
|
*/
|
||||||
using mqtt_callback_t = std::function<void(const std::string &, const std::string &)>;
|
using mqtt_callback_t = std::function<void(const std::string &, const std::string &)>;
|
||||||
using mqtt_json_callback_t = std::function<void(const std::string &, JsonObject &)>;
|
using mqtt_json_callback_t = std::function<void(const std::string &, JsonObject)>;
|
||||||
|
|
||||||
/// internal struct for MQTT messages.
|
/// internal struct for MQTT messages.
|
||||||
struct MQTTMessage {
|
struct MQTTMessage {
|
||||||
|
@ -306,11 +306,11 @@ class MQTTMessageTrigger : public Trigger<std::string>, public Component {
|
||||||
optional<std::string> payload_;
|
optional<std::string> payload_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MQTTJsonMessageTrigger : public Trigger<const JsonObject &> {
|
class MQTTJsonMessageTrigger : public Trigger<JsonObjectConst> {
|
||||||
public:
|
public:
|
||||||
explicit MQTTJsonMessageTrigger(const std::string &topic, uint8_t qos) {
|
explicit MQTTJsonMessageTrigger(const std::string &topic, uint8_t qos) {
|
||||||
global_mqtt_client->subscribe_json(
|
global_mqtt_client->subscribe_json(
|
||||||
topic, [this](const std::string &topic, JsonObject &root) { this->trigger(root); }, qos);
|
topic, [this](const std::string &topic, JsonObject root) { this->trigger(root); }, qos);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ template<typename... Ts> class MQTTPublishJsonAction : public Action<Ts...> {
|
||||||
TEMPLATABLE_VALUE(uint8_t, qos)
|
TEMPLATABLE_VALUE(uint8_t, qos)
|
||||||
TEMPLATABLE_VALUE(bool, retain)
|
TEMPLATABLE_VALUE(bool, retain)
|
||||||
|
|
||||||
void set_payload(std::function<void(Ts..., JsonObject &)> payload) { this->payload_ = payload; }
|
void set_payload(std::function<void(Ts..., JsonObject)> payload) { this->payload_ = payload; }
|
||||||
|
|
||||||
void play(Ts... x) override {
|
void play(Ts... x) override {
|
||||||
auto f = std::bind(&MQTTPublishJsonAction<Ts...>::encode_, this, x..., std::placeholders::_1);
|
auto f = std::bind(&MQTTPublishJsonAction<Ts...>::encode_, this, x..., std::placeholders::_1);
|
||||||
|
@ -349,8 +349,8 @@ template<typename... Ts> class MQTTPublishJsonAction : public Action<Ts...> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void encode_(Ts... x, JsonObject &root) { this->payload_(x..., root); }
|
void encode_(Ts... x, JsonObject root) { this->payload_(x..., root); }
|
||||||
std::function<void(Ts..., JsonObject &)> payload_;
|
std::function<void(Ts..., JsonObject)> payload_;
|
||||||
MQTTClientComponent *parent_;
|
MQTTClientComponent *parent_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ static const char *const TAG = "mqtt.climate";
|
||||||
|
|
||||||
using namespace esphome::climate;
|
using namespace esphome::climate;
|
||||||
|
|
||||||
void MQTTClimateComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
auto traits = this->device_->get_traits();
|
auto traits = this->device_->get_traits();
|
||||||
// current_temperature_topic
|
// current_temperature_topic
|
||||||
if (traits.get_supports_current_temperature()) {
|
if (traits.get_supports_current_temperature()) {
|
||||||
|
@ -25,7 +25,7 @@ void MQTTClimateComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryC
|
||||||
// mode_state_topic
|
// mode_state_topic
|
||||||
root[MQTT_MODE_STATE_TOPIC] = this->get_mode_state_topic();
|
root[MQTT_MODE_STATE_TOPIC] = this->get_mode_state_topic();
|
||||||
// modes
|
// modes
|
||||||
JsonArray &modes = root.createNestedArray(MQTT_MODES);
|
JsonArray modes = root.createNestedArray(MQTT_MODES);
|
||||||
// sort array for nice UI in HA
|
// sort array for nice UI in HA
|
||||||
if (traits.supports_mode(CLIMATE_MODE_AUTO))
|
if (traits.supports_mode(CLIMATE_MODE_AUTO))
|
||||||
modes.add("auto");
|
modes.add("auto");
|
||||||
|
@ -83,7 +83,7 @@ void MQTTClimateComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryC
|
||||||
// fan_mode_state_topic
|
// fan_mode_state_topic
|
||||||
root[MQTT_FAN_MODE_STATE_TOPIC] = this->get_fan_mode_state_topic();
|
root[MQTT_FAN_MODE_STATE_TOPIC] = this->get_fan_mode_state_topic();
|
||||||
// fan_modes
|
// fan_modes
|
||||||
JsonArray &fan_modes = root.createNestedArray("fan_modes");
|
JsonArray fan_modes = root.createNestedArray("fan_modes");
|
||||||
if (traits.supports_fan_mode(CLIMATE_FAN_ON))
|
if (traits.supports_fan_mode(CLIMATE_FAN_ON))
|
||||||
fan_modes.add("on");
|
fan_modes.add("on");
|
||||||
if (traits.supports_fan_mode(CLIMATE_FAN_OFF))
|
if (traits.supports_fan_mode(CLIMATE_FAN_OFF))
|
||||||
|
@ -112,7 +112,7 @@ void MQTTClimateComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryC
|
||||||
// swing_mode_state_topic
|
// swing_mode_state_topic
|
||||||
root[MQTT_SWING_MODE_STATE_TOPIC] = this->get_swing_mode_state_topic();
|
root[MQTT_SWING_MODE_STATE_TOPIC] = this->get_swing_mode_state_topic();
|
||||||
// swing_modes
|
// swing_modes
|
||||||
JsonArray &swing_modes = root.createNestedArray("swing_modes");
|
JsonArray swing_modes = root.createNestedArray("swing_modes");
|
||||||
if (traits.supports_swing_mode(CLIMATE_SWING_OFF))
|
if (traits.supports_swing_mode(CLIMATE_SWING_OFF))
|
||||||
swing_modes.add("off");
|
swing_modes.add("off");
|
||||||
if (traits.supports_swing_mode(CLIMATE_SWING_BOTH))
|
if (traits.supports_swing_mode(CLIMATE_SWING_BOTH))
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace mqtt {
|
||||||
class MQTTClimateComponent : public mqtt::MQTTComponent {
|
class MQTTClimateComponent : public mqtt::MQTTComponent {
|
||||||
public:
|
public:
|
||||||
MQTTClimateComponent(climate::Climate *device);
|
MQTTClimateComponent(climate::Climate *device);
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
bool send_initial_state() override;
|
bool send_initial_state() override;
|
||||||
std::string component_type() const override;
|
std::string component_type() const override;
|
||||||
void setup() override;
|
void setup() override;
|
||||||
|
|
|
@ -63,7 +63,7 @@ bool MQTTComponent::send_discovery_() {
|
||||||
|
|
||||||
return global_mqtt_client->publish_json(
|
return global_mqtt_client->publish_json(
|
||||||
this->get_discovery_topic_(discovery_info),
|
this->get_discovery_topic_(discovery_info),
|
||||||
[this](JsonObject &root) {
|
[this](JsonObject root) {
|
||||||
SendDiscoveryConfig config;
|
SendDiscoveryConfig config;
|
||||||
config.state_topic = true;
|
config.state_topic = true;
|
||||||
config.command_topic = true;
|
config.command_topic = true;
|
||||||
|
@ -127,7 +127,7 @@ bool MQTTComponent::send_discovery_() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject &device_info = root.createNestedObject(MQTT_DEVICE);
|
JsonObject device_info = root.createNestedObject(MQTT_DEVICE);
|
||||||
device_info[MQTT_DEVICE_IDENTIFIERS] = get_mac_address();
|
device_info[MQTT_DEVICE_IDENTIFIERS] = get_mac_address();
|
||||||
device_info[MQTT_DEVICE_NAME] = node_name;
|
device_info[MQTT_DEVICE_NAME] = node_name;
|
||||||
device_info[MQTT_DEVICE_SW_VERSION] = "esphome v" ESPHOME_VERSION " " + App.get_compilation_time();
|
device_info[MQTT_DEVICE_SW_VERSION] = "esphome v" ESPHOME_VERSION " " + App.get_compilation_time();
|
||||||
|
|
|
@ -70,7 +70,7 @@ class MQTTComponent : public Component {
|
||||||
void call_dump_config() override;
|
void call_dump_config() override;
|
||||||
|
|
||||||
/// Send discovery info the Home Assistant, override this.
|
/// Send discovery info the Home Assistant, override this.
|
||||||
virtual void send_discovery(JsonObject &root, SendDiscoveryConfig &config) = 0;
|
virtual void send_discovery(JsonObject root, SendDiscoveryConfig &config) = 0;
|
||||||
|
|
||||||
virtual bool send_initial_state() = 0;
|
virtual bool send_initial_state() = 0;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ void MQTTCoverComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, " Tilt Command Topic: '%s'", this->get_tilt_command_topic().c_str());
|
ESP_LOGCONFIG(TAG, " Tilt Command Topic: '%s'", this->get_tilt_command_topic().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void MQTTCoverComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
if (!this->cover_->get_device_class().empty())
|
if (!this->cover_->get_device_class().empty())
|
||||||
root[MQTT_DEVICE_CLASS] = this->cover_->get_device_class();
|
root[MQTT_DEVICE_CLASS] = this->cover_->get_device_class();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class MQTTCoverComponent : public mqtt::MQTTComponent {
|
||||||
explicit MQTTCoverComponent(cover::Cover *cover);
|
explicit MQTTCoverComponent(cover::Cover *cover);
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
MQTT_COMPONENT_CUSTOM_TOPIC(position, command)
|
MQTT_COMPONENT_CUSTOM_TOPIC(position, command)
|
||||||
MQTT_COMPONENT_CUSTOM_TOPIC(position, state)
|
MQTT_COMPONENT_CUSTOM_TOPIC(position, state)
|
||||||
|
|
|
@ -120,7 +120,7 @@ void MQTTFanComponent::dump_config() {
|
||||||
|
|
||||||
bool MQTTFanComponent::send_initial_state() { return this->publish_state(); }
|
bool MQTTFanComponent::send_initial_state() { return this->publish_state(); }
|
||||||
|
|
||||||
void MQTTFanComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTFanComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
if (this->state_->get_traits().supports_oscillation()) {
|
if (this->state_->get_traits().supports_oscillation()) {
|
||||||
root[MQTT_OSCILLATION_COMMAND_TOPIC] = this->get_oscillation_command_topic();
|
root[MQTT_OSCILLATION_COMMAND_TOPIC] = this->get_oscillation_command_topic();
|
||||||
root[MQTT_OSCILLATION_STATE_TOPIC] = this->get_oscillation_state_topic();
|
root[MQTT_OSCILLATION_STATE_TOPIC] = this->get_oscillation_state_topic();
|
||||||
|
|
|
@ -22,7 +22,7 @@ class MQTTFanComponent : public mqtt::MQTTComponent {
|
||||||
MQTT_COMPONENT_CUSTOM_TOPIC(speed, command)
|
MQTT_COMPONENT_CUSTOM_TOPIC(speed, command)
|
||||||
MQTT_COMPONENT_CUSTOM_TOPIC(speed, state)
|
MQTT_COMPONENT_CUSTOM_TOPIC(speed, state)
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
// ========== INTERNAL METHODS ==========
|
// ========== INTERNAL METHODS ==========
|
||||||
// (In most use cases you won't need these)
|
// (In most use cases you won't need these)
|
||||||
|
|
|
@ -18,7 +18,7 @@ std::string MQTTJSONLightComponent::component_type() const { return "light"; }
|
||||||
const EntityBase *MQTTJSONLightComponent::get_entity() const { return this->state_; }
|
const EntityBase *MQTTJSONLightComponent::get_entity() const { return this->state_; }
|
||||||
|
|
||||||
void MQTTJSONLightComponent::setup() {
|
void MQTTJSONLightComponent::setup() {
|
||||||
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject &root) {
|
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) {
|
||||||
LightCall call = this->state_->make_call();
|
LightCall call = this->state_->make_call();
|
||||||
LightJSONSchema::parse_json(*this->state_, call, root);
|
LightJSONSchema::parse_json(*this->state_, call, root);
|
||||||
call.perform();
|
call.perform();
|
||||||
|
@ -32,16 +32,16 @@ MQTTJSONLightComponent::MQTTJSONLightComponent(LightState *state) : MQTTComponen
|
||||||
|
|
||||||
bool MQTTJSONLightComponent::publish_state_() {
|
bool MQTTJSONLightComponent::publish_state_() {
|
||||||
return this->publish_json(this->get_state_topic_(),
|
return this->publish_json(this->get_state_topic_(),
|
||||||
[this](JsonObject &root) { LightJSONSchema::dump_json(*this->state_, root); });
|
[this](JsonObject root) { LightJSONSchema::dump_json(*this->state_, root); });
|
||||||
}
|
}
|
||||||
LightState *MQTTJSONLightComponent::get_state() const { return this->state_; }
|
LightState *MQTTJSONLightComponent::get_state() const { return this->state_; }
|
||||||
|
|
||||||
void MQTTJSONLightComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
root["schema"] = "json";
|
root["schema"] = "json";
|
||||||
auto traits = this->state_->get_traits();
|
auto traits = this->state_->get_traits();
|
||||||
|
|
||||||
root[MQTT_COLOR_MODE] = true;
|
root[MQTT_COLOR_MODE] = true;
|
||||||
JsonArray &color_modes = root.createNestedArray("supported_color_modes");
|
JsonArray color_modes = root.createNestedArray("supported_color_modes");
|
||||||
if (traits.supports_color_mode(ColorMode::ON_OFF))
|
if (traits.supports_color_mode(ColorMode::ON_OFF))
|
||||||
color_modes.add("onoff");
|
color_modes.add("onoff");
|
||||||
if (traits.supports_color_mode(ColorMode::BRIGHTNESS))
|
if (traits.supports_color_mode(ColorMode::BRIGHTNESS))
|
||||||
|
@ -66,7 +66,7 @@ void MQTTJSONLightComponent::send_discovery(JsonObject &root, mqtt::SendDiscover
|
||||||
|
|
||||||
if (this->state_->supports_effects()) {
|
if (this->state_->supports_effects()) {
|
||||||
root["effect"] = true;
|
root["effect"] = true;
|
||||||
JsonArray &effect_list = root.createNestedArray(MQTT_EFFECT_LIST);
|
JsonArray effect_list = root.createNestedArray(MQTT_EFFECT_LIST);
|
||||||
for (auto *effect : this->state_->get_effects())
|
for (auto *effect : this->state_->get_effects())
|
||||||
effect_list.add(effect->get_name());
|
effect_list.add(effect->get_name());
|
||||||
effect_list.add("None");
|
effect_list.add("None");
|
||||||
|
|
|
@ -21,7 +21,7 @@ class MQTTJSONLightComponent : public mqtt::MQTTComponent {
|
||||||
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
bool send_initial_state() override;
|
bool send_initial_state() override;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ void MQTTNumberComponent::dump_config() {
|
||||||
std::string MQTTNumberComponent::component_type() const { return "number"; }
|
std::string MQTTNumberComponent::component_type() const { return "number"; }
|
||||||
const EntityBase *MQTTNumberComponent::get_entity() const { return this->number_; }
|
const EntityBase *MQTTNumberComponent::get_entity() const { return this->number_; }
|
||||||
|
|
||||||
void MQTTNumberComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
const auto &traits = number_->traits;
|
const auto &traits = number_->traits;
|
||||||
// https://www.home-assistant.io/integrations/number.mqtt/
|
// https://www.home-assistant.io/integrations/number.mqtt/
|
||||||
root[MQTT_MIN] = traits.get_min_value();
|
root[MQTT_MIN] = traits.get_min_value();
|
||||||
|
|
|
@ -25,7 +25,7 @@ class MQTTNumberComponent : public mqtt::MQTTComponent {
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
bool send_initial_state() override;
|
bool send_initial_state() override;
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,10 @@ void MQTTSelectComponent::dump_config() {
|
||||||
std::string MQTTSelectComponent::component_type() const { return "select"; }
|
std::string MQTTSelectComponent::component_type() const { return "select"; }
|
||||||
const EntityBase *MQTTSelectComponent::get_entity() const { return this->select_; }
|
const EntityBase *MQTTSelectComponent::get_entity() const { return this->select_; }
|
||||||
|
|
||||||
void MQTTSelectComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTSelectComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
const auto &traits = select_->traits;
|
const auto &traits = select_->traits;
|
||||||
// https://www.home-assistant.io/integrations/select.mqtt/
|
// https://www.home-assistant.io/integrations/select.mqtt/
|
||||||
JsonArray &options = root.createNestedArray(MQTT_OPTIONS);
|
JsonArray options = root.createNestedArray(MQTT_OPTIONS);
|
||||||
for (const auto &option : traits.get_options())
|
for (const auto &option : traits.get_options())
|
||||||
options.add(option);
|
options.add(option);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ class MQTTSelectComponent : public mqtt::MQTTComponent {
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
bool send_initial_state() override;
|
bool send_initial_state() override;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ uint32_t MQTTSensorComponent::get_expire_after() const {
|
||||||
void MQTTSensorComponent::set_expire_after(uint32_t expire_after) { this->expire_after_ = expire_after; }
|
void MQTTSensorComponent::set_expire_after(uint32_t expire_after) { this->expire_after_ = expire_after; }
|
||||||
void MQTTSensorComponent::disable_expire_after() { this->expire_after_ = 0; }
|
void MQTTSensorComponent::disable_expire_after() { this->expire_after_ = 0; }
|
||||||
|
|
||||||
void MQTTSensorComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
if (!this->sensor_->get_device_class().empty())
|
if (!this->sensor_->get_device_class().empty())
|
||||||
root[MQTT_DEVICE_CLASS] = this->sensor_->get_device_class();
|
root[MQTT_DEVICE_CLASS] = this->sensor_->get_device_class();
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class MQTTSensorComponent : public mqtt::MQTTComponent {
|
||||||
/// Disable Home Assistant value expiry.
|
/// Disable Home Assistant value expiry.
|
||||||
void disable_expire_after();
|
void disable_expire_after();
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
// ========== INTERNAL METHODS ==========
|
// ========== INTERNAL METHODS ==========
|
||||||
// (In most use cases you won't need these)
|
// (In most use cases you won't need these)
|
||||||
|
|
|
@ -44,7 +44,7 @@ void MQTTSwitchComponent::dump_config() {
|
||||||
|
|
||||||
std::string MQTTSwitchComponent::component_type() const { return "switch"; }
|
std::string MQTTSwitchComponent::component_type() const { return "switch"; }
|
||||||
const EntityBase *MQTTSwitchComponent::get_entity() const { return this->switch_; }
|
const EntityBase *MQTTSwitchComponent::get_entity() const { return this->switch_; }
|
||||||
void MQTTSwitchComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTSwitchComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
if (this->switch_->assumed_state())
|
if (this->switch_->assumed_state())
|
||||||
root[MQTT_OPTIMISTIC] = true;
|
root[MQTT_OPTIMISTIC] = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class MQTTSwitchComponent : public mqtt::MQTTComponent {
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
bool send_initial_state() override;
|
bool send_initial_state() override;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ static const char *const TAG = "mqtt.text_sensor";
|
||||||
using namespace esphome::text_sensor;
|
using namespace esphome::text_sensor;
|
||||||
|
|
||||||
MQTTTextSensor::MQTTTextSensor(TextSensor *sensor) : MQTTComponent(), sensor_(sensor) {}
|
MQTTTextSensor::MQTTTextSensor(TextSensor *sensor) : MQTTComponent(), sensor_(sensor) {}
|
||||||
void MQTTTextSensor::send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) {
|
void MQTTTextSensor::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
config.command_topic = false;
|
config.command_topic = false;
|
||||||
}
|
}
|
||||||
void MQTTTextSensor::setup() {
|
void MQTTTextSensor::setup() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ class MQTTTextSensor : public mqtt::MQTTComponent {
|
||||||
public:
|
public:
|
||||||
explicit MQTTTextSensor(text_sensor::TextSensor *sensor);
|
explicit MQTTTextSensor(text_sensor::TextSensor *sensor);
|
||||||
|
|
||||||
void send_discovery(JsonObject &root, mqtt::SendDiscoveryConfig &config) override;
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,7 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::sensor_json(sensor::Sensor *obj, float value) {
|
std::string WebServer::sensor_json(sensor::Sensor *obj, float value) {
|
||||||
return json::build_json([obj, value](JsonObject &root) {
|
return json::build_json([obj, value](JsonObject root) {
|
||||||
root["id"] = "sensor-" + obj->get_object_id();
|
root["id"] = "sensor-" + obj->get_object_id();
|
||||||
std::string state = value_accuracy_to_string(value, obj->get_accuracy_decimals());
|
std::string state = value_accuracy_to_string(value, obj->get_accuracy_decimals());
|
||||||
if (!obj->get_unit_of_measurement().empty())
|
if (!obj->get_unit_of_measurement().empty())
|
||||||
|
@ -342,7 +342,7 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std::string &value) {
|
std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std::string &value) {
|
||||||
return json::build_json([obj, value](JsonObject &root) {
|
return json::build_json([obj, value](JsonObject root) {
|
||||||
root["id"] = "text_sensor-" + obj->get_object_id();
|
root["id"] = "text_sensor-" + obj->get_object_id();
|
||||||
root["state"] = value;
|
root["state"] = value;
|
||||||
root["value"] = value;
|
root["value"] = value;
|
||||||
|
@ -355,7 +355,7 @@ void WebServer::on_switch_update(switch_::Switch *obj, bool state) {
|
||||||
this->events_.send(this->switch_json(obj, state).c_str(), "state");
|
this->events_.send(this->switch_json(obj, state).c_str(), "state");
|
||||||
}
|
}
|
||||||
std::string WebServer::switch_json(switch_::Switch *obj, bool value) {
|
std::string WebServer::switch_json(switch_::Switch *obj, bool value) {
|
||||||
return json::build_json([obj, value](JsonObject &root) {
|
return json::build_json([obj, value](JsonObject root) {
|
||||||
root["id"] = "switch-" + obj->get_object_id();
|
root["id"] = "switch-" + obj->get_object_id();
|
||||||
root["state"] = value ? "ON" : "OFF";
|
root["state"] = value ? "ON" : "OFF";
|
||||||
root["value"] = value;
|
root["value"] = value;
|
||||||
|
@ -410,7 +410,7 @@ void WebServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool s
|
||||||
this->events_.send(this->binary_sensor_json(obj, state).c_str(), "state");
|
this->events_.send(this->binary_sensor_json(obj, state).c_str(), "state");
|
||||||
}
|
}
|
||||||
std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool value) {
|
std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool value) {
|
||||||
return json::build_json([obj, value](JsonObject &root) {
|
return json::build_json([obj, value](JsonObject root) {
|
||||||
root["id"] = "binary_sensor-" + obj->get_object_id();
|
root["id"] = "binary_sensor-" + obj->get_object_id();
|
||||||
root["state"] = value ? "ON" : "OFF";
|
root["state"] = value ? "ON" : "OFF";
|
||||||
root["value"] = value;
|
root["value"] = value;
|
||||||
|
@ -431,7 +431,7 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con
|
||||||
#ifdef USE_FAN
|
#ifdef USE_FAN
|
||||||
void WebServer::on_fan_update(fan::FanState *obj) { this->events_.send(this->fan_json(obj).c_str(), "state"); }
|
void WebServer::on_fan_update(fan::FanState *obj) { this->events_.send(this->fan_json(obj).c_str(), "state"); }
|
||||||
std::string WebServer::fan_json(fan::FanState *obj) {
|
std::string WebServer::fan_json(fan::FanState *obj) {
|
||||||
return json::build_json([obj](JsonObject &root) {
|
return json::build_json([obj](JsonObject root) {
|
||||||
root["id"] = "fan-" + obj->get_object_id();
|
root["id"] = "fan-" + obj->get_object_id();
|
||||||
root["state"] = obj->state ? "ON" : "OFF";
|
root["state"] = obj->state ? "ON" : "OFF";
|
||||||
root["value"] = obj->state;
|
root["value"] = obj->state;
|
||||||
|
@ -580,7 +580,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::light_json(light::LightState *obj) {
|
std::string WebServer::light_json(light::LightState *obj) {
|
||||||
return json::build_json([obj](JsonObject &root) {
|
return json::build_json([obj](JsonObject root) {
|
||||||
root["id"] = "light-" + obj->get_object_id();
|
root["id"] = "light-" + obj->get_object_id();
|
||||||
root["state"] = obj->remote_values.is_on() ? "ON" : "OFF";
|
root["state"] = obj->remote_values.is_on() ? "ON" : "OFF";
|
||||||
light::LightJSONSchema::dump_json(*obj, root);
|
light::LightJSONSchema::dump_json(*obj, root);
|
||||||
|
@ -632,7 +632,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::cover_json(cover::Cover *obj) {
|
std::string WebServer::cover_json(cover::Cover *obj) {
|
||||||
return json::build_json([obj](JsonObject &root) {
|
return json::build_json([obj](JsonObject root) {
|
||||||
root["id"] = "cover-" + obj->get_object_id();
|
root["id"] = "cover-" + obj->get_object_id();
|
||||||
root["state"] = obj->is_fully_closed() ? "CLOSED" : "OPEN";
|
root["state"] = obj->is_fully_closed() ? "CLOSED" : "OPEN";
|
||||||
root["value"] = obj->position;
|
root["value"] = obj->position;
|
||||||
|
@ -659,7 +659,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::number_json(number::Number *obj, float value) {
|
std::string WebServer::number_json(number::Number *obj, float value) {
|
||||||
return json::build_json([obj, value](JsonObject &root) {
|
return json::build_json([obj, value](JsonObject root) {
|
||||||
root["id"] = "number-" + obj->get_object_id();
|
root["id"] = "number-" + obj->get_object_id();
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
snprintf(buffer, sizeof(buffer), "%f", value);
|
snprintf(buffer, sizeof(buffer), "%f", value);
|
||||||
|
@ -703,7 +703,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::select_json(select::Select *obj, const std::string &value) {
|
std::string WebServer::select_json(select::Select *obj, const std::string &value) {
|
||||||
return json::build_json([obj, value](JsonObject &root) {
|
return json::build_json([obj, value](JsonObject root) {
|
||||||
root["id"] = "select-" + obj->get_object_id();
|
root["id"] = "select-" + obj->get_object_id();
|
||||||
root["state"] = value;
|
root["state"] = value;
|
||||||
root["value"] = value;
|
root["value"] = value;
|
||||||
|
|
|
@ -27,8 +27,7 @@ Application = esphome_ns.class_("Application")
|
||||||
optional = esphome_ns.class_("optional")
|
optional = esphome_ns.class_("optional")
|
||||||
arduino_json_ns = global_ns.namespace("ArduinoJson")
|
arduino_json_ns = global_ns.namespace("ArduinoJson")
|
||||||
JsonObject = arduino_json_ns.class_("JsonObject")
|
JsonObject = arduino_json_ns.class_("JsonObject")
|
||||||
JsonObjectRef = JsonObject.operator("ref")
|
JsonObjectConst = arduino_json_ns.class_("JsonObjectConst")
|
||||||
JsonObjectConstRef = JsonObjectRef.operator("const")
|
|
||||||
Controller = esphome_ns.class_("Controller")
|
Controller = esphome_ns.class_("Controller")
|
||||||
GPIOPin = esphome_ns.class_("GPIOPin")
|
GPIOPin = esphome_ns.class_("GPIOPin")
|
||||||
InternalGPIOPin = esphome_ns.class_("InternalGPIOPin", GPIOPin)
|
InternalGPIOPin = esphome_ns.class_("InternalGPIOPin", GPIOPin)
|
||||||
|
|
|
@ -30,6 +30,7 @@ lib_deps =
|
||||||
esphome/noise-c@0.1.4 ; api
|
esphome/noise-c@0.1.4 ; api
|
||||||
makuna/NeoPixelBus@2.6.9 ; neopixelbus
|
makuna/NeoPixelBus@2.6.9 ; neopixelbus
|
||||||
esphome/Improv@1.0.0 ; improv_serial / esp32_improv
|
esphome/Improv@1.0.0 ; improv_serial / esp32_improv
|
||||||
|
bblanchon/ArduinoJson@6.18.5 ; json
|
||||||
build_flags =
|
build_flags =
|
||||||
-DESPHOME_LOG_LEVEL=ESPHOME_LOG_LEVEL_VERY_VERBOSE
|
-DESPHOME_LOG_LEVEL=ESPHOME_LOG_LEVEL_VERY_VERBOSE
|
||||||
src_filter =
|
src_filter =
|
||||||
|
@ -42,7 +43,6 @@ extends = common
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${common.lib_deps}
|
${common.lib_deps}
|
||||||
ottowinter/AsyncMqttClient-esphome@0.8.6 ; mqtt
|
ottowinter/AsyncMqttClient-esphome@0.8.6 ; mqtt
|
||||||
ottowinter/ArduinoJson-esphomelib@5.13.3 ; json
|
|
||||||
esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base
|
esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base
|
||||||
fastled/FastLED@3.3.2 ; fastled_base
|
fastled/FastLED@3.3.2 ; fastled_base
|
||||||
mikalhart/TinyGPSPlus@1.0.2 ; gps
|
mikalhart/TinyGPSPlus@1.0.2 ; gps
|
||||||
|
|
|
@ -68,8 +68,7 @@ from esphome import codegen as cg
|
||||||
"optional",
|
"optional",
|
||||||
"arduino_json_ns",
|
"arduino_json_ns",
|
||||||
"JsonObject",
|
"JsonObject",
|
||||||
"JsonObjectRef",
|
"JsonObjectConst",
|
||||||
"JsonObjectConstRef",
|
|
||||||
"Controller",
|
"Controller",
|
||||||
"GPIOPin",
|
"GPIOPin",
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue