Merge branch 'v1.3.1'

This commit is contained in:
Nicu Hodos 2024-10-15 17:25:30 +02:00
commit df1b900b5d
2 changed files with 59 additions and 51 deletions

View File

@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json",
"name": "ha-mqtt",
"version": "1.3.0",
"version": "1.3.1",
"description": "Home Assistant classes for integration with MQTT auto discovery",
"repository": {
"type": "git",

108
src/ha.h
View File

@ -12,7 +12,9 @@ namespace Ha {
uint16_t(*publisher)(const char* topic, const char* message);
typedef void (*onMessage)(const char* msg);
struct Component;
struct DeviceConfig {
friend struct Component;
const char* id = nullptr;
const char* name = nullptr;
const char* model = nullptr;
@ -24,17 +26,6 @@ namespace Ha {
return *(new DeviceConfig{ id });
}
void buildConfig(JsonDocument& jsonDoc) {
JsonObject device = jsonDoc.createNestedObject("device");
if (name) device["name"] = name;
if (model) device["model"] = model;
if (manufacturer) device["manufacturer"] = manufacturer;
if (area) device["suggested_area"] = area;
if (parent) device["via_device"] = parent->id;
JsonArray identifiers = device.createNestedArray("identifiers");
identifiers.add(id);
}
DeviceConfig& withName(const char* value) {
name = value;
return *this;
@ -62,6 +53,17 @@ namespace Ha {
protected:
DeviceConfig(const char* id) : id(id) {}
void buildConfig(JsonDocument& jsonDoc) {
JsonObject device = jsonDoc.createNestedObject("device");
if (name) device["name"] = name;
if (model) device["model"] = model;
if (manufacturer) device["manufacturer"] = manufacturer;
if (area) device["suggested_area"] = area;
if (parent) device["via_device"] = parent->id;
JsonArray identifiers = device.createNestedArray("identifiers");
identifiers.add(id);
}
};
struct Component {
@ -99,6 +101,21 @@ namespace Ha {
components.add(this);
}
void publishConfig() {
StaticJsonDocument<JSON_SIZE> jsonDoc;
buildConfig(jsonDoc);
char message[JSON_SIZE];
serializeJson(jsonDoc, message);
publisher(configTopic, message);
}
void publishCleanupConfig() {
publisher(configTopic, "");
}
protected:
virtual void buildUniqueId(char* uniqueId) {
sprintf(uniqueId, "%s_%s", MAIN_DEVICE_ID, id);
}
@ -125,33 +142,20 @@ namespace Ha {
jsonNumbers.addToJson(jsonDoc);
jsonStrings.addToJson(jsonDoc);
}
void publishConfig() {
StaticJsonDocument<JSON_SIZE> jsonDoc;
buildConfig(jsonDoc);
char message[JSON_SIZE];
serializeJson(jsonDoc, message);
publisher(configTopic, message);
}
void publishCleanupConfig() {
publisher(configTopic, "");
}
};
struct AbstractBuilder {
static List<AbstractBuilder> builders;
AbstractBuilder() {
builders.add(this);
}
static void deleteAll() {
builders.forEach([](AbstractBuilder* builder) { delete builder; });
builders.empty();
}
protected:
AbstractBuilder() {
builders.add(this);
}
};
template <class T>
@ -255,8 +259,6 @@ namespace Ha {
struct Command : Component {
bool retain = false;
char commandTopic[TOPIC_SIZE];
onMessage f;
static unordered_map<string, Command*> mapCommands;
Command(const char* name, const char* id, const char* type, onMessage f) : Component(name, id, type), f(f) {
@ -268,6 +270,9 @@ namespace Ha {
if (f) f(msg);
}
protected:
char commandTopic[TOPIC_SIZE];
onMessage f;
virtual void buildCommandConfig(JsonDocument& jsonDoc) = 0;
void buildComponentConfig(JsonDocument& jsonDoc) override {
@ -275,21 +280,19 @@ namespace Ha {
if (retain) jsonDoc["retain"] = true;
buildCommandConfig(jsonDoc);
}
};
struct Button : Command {
Button(const char* name, const char* id, onMessage f = nullptr) : Command(name, id, "button", f) {}
protected:
void buildCommandConfig(JsonDocument& jsonDoc) override {}
};
struct StateConfig {
char stateTopic[TOPIC_SIZE];
static unordered_map<string, Command*> mapStateTopics;
Component* cmp;
StateConfig(Component* cmp) : cmp(cmp) {}
@ -297,23 +300,22 @@ namespace Ha {
sprintf(stateTopic, "homeassistant/%s/%s/%s/state", cmp->type, MAIN_DEVICE_ID, cmp->id);
}
void buildConfig(JsonDocument& jsonDoc) {
if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic;
}
void updateState(const char* message) {
if (stateTopic[0]) publisher(stateTopic, message);
}
protected:
char stateTopic[TOPIC_SIZE];
Component* cmp;
void buildConfig(JsonDocument& jsonDoc) {
if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic;
}
};
struct Switch : Command, StateConfig {
Switch(const char* name, const char* id, onMessage f = nullptr) : Command(name, id, "switch", f), StateConfig(this) {}
void buildCommandConfig(JsonDocument& jsonDoc) override {
StateConfig::buildConfig(jsonDoc);
}
void updateState(bool state) {
StateConfig::updateState(state ? "ON" : "OFF");
}
@ -321,6 +323,11 @@ namespace Ha {
void restoreFromState() {
mapStateTopics.insert({stateTopic, this});
}
protected:
void buildCommandConfig(JsonDocument& jsonDoc) override {
StateConfig::buildConfig(jsonDoc);
}
};
struct Number : Command, StateConfig {
@ -329,13 +336,6 @@ namespace Ha {
Number(const char* name, const char* id, unsigned int min, unsigned int max, unsigned int step, onMessage f)
: Command(name, id, "number", f), StateConfig(this), min(min), max(max), step(step) {}
void buildCommandConfig(JsonDocument& jsonDoc) override {
StateConfig::buildConfig(jsonDoc);
jsonDoc["min"] = min;
jsonDoc["max"] = max;
jsonDoc["step"] = step;
}
void updateState(unsigned int value) {
char message[32];
sprintf(message, "%u", value);
@ -346,6 +346,13 @@ namespace Ha {
mapStateTopics.insert({stateTopic, this});
}
protected:
void buildCommandConfig(JsonDocument& jsonDoc) override {
StateConfig::buildConfig(jsonDoc);
jsonDoc["min"] = min;
jsonDoc["max"] = max;
jsonDoc["step"] = step;
}
};
struct Sensor : Component, StateConfig {
@ -356,9 +363,10 @@ namespace Ha {
Sensor(const char* name, const char* id) : Component(name, id, "sensor"), StateConfig(this) {
withStateTopic();
mapSensors.insert({ id, this });
mapSensors.insert({ string(id), this });
}
protected:
void buildUniqueId(char* uniqueId) override {
if (multiValueComponent && deviceClass) {
sprintf(uniqueId, "%s_%s_%s", MAIN_DEVICE_ID, deviceClass, id);