added oil tank room sensor

This commit is contained in:
Nicu Hodos 2024-05-04 21:46:39 +02:00
parent 18450a6883
commit 6fd9bdc8ce
6 changed files with 83 additions and 29 deletions

View File

@ -33,4 +33,16 @@ public:
} }
} }
static char* buildId(const char* id) {
char* uId = new char[30];
sprintf(uId, "%s", id);
return uId;
}
static char* buildId(unsigned int id) {
char* uId = new char[30];
sprintf(uId, "%d", id);
return uId;
}
}; };

View File

@ -6,9 +6,11 @@ bool buildSensorJson(unsigned long value, JsonDocument& jsonDoc) {
sensor["id"] = ID(value); sensor["id"] = ID(value);
float voltage = (float)GET_VCC(value) / 1000; float voltage = (float)GET_VCC(value) / 1000;
JsonObject diagnostic = sensor.createNestedObject("diagnostic");
if (voltage != 0) { if (voltage != 0) {
JsonObject diagnostic = sensor.createNestedObject("diagnostic");
diagnostic["voltage"] = voltage; diagnostic["voltage"] = voltage;
} else {
diagnostic["voltage"] = "";
} }
switch (GET_TYPE(value)) { switch (GET_TYPE(value)) {

View File

@ -9,6 +9,14 @@ using namespace Ha;
DeviceConfig* gatewayDevice = (new DeviceConfig{MAIN_DEVICE_ID, "RC Gateway"})->withManufacturer("Adafruit")->withModel("Huzzah Esp8266"); DeviceConfig* gatewayDevice = (new DeviceConfig{MAIN_DEVICE_ID, "RC Gateway"})->withManufacturer("Adafruit")->withModel("Huzzah Esp8266");
DeviceConfig* atTinyDevice = (new DeviceConfig{})->withManufacturer("Atmel")->withModel("AtTiny85")->withParent(gatewayDevice); DeviceConfig* atTinyDevice = (new DeviceConfig{})->withManufacturer("Atmel")->withModel("AtTiny85")->withParent(gatewayDevice);
struct SensorBuilder {
static Sensor* withVoltage(Sensor* sensor) {
(new VoltageSensor{sensor->id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"})->asDevice(new DeviceConfig{sensor->mainDevice->id});
(new BatterySensor{sensor->id, "Battery level", "{{ ((states('sensor.oil_tank_room_battery_voltage')|float-2.5)|round(2)*100/2)|int }}"})->asDevice(new DeviceConfig{sensor->mainDevice->id});
return sensor;
}
};
struct PollinSwitch : Switch { struct PollinSwitch : Switch {
const char* group; const char* group;
unsigned char channel; unsigned char channel;

View File

@ -18,22 +18,19 @@ namespace Ha {
DeviceConfig* parent = nullptr; DeviceConfig* parent = nullptr;
DeviceConfig() {} DeviceConfig() {}
DeviceConfig(const char* id) : id(id) {}
DeviceConfig(const char* id, const char* name) : id(id), name(name) {} DeviceConfig(const char* id, const char* name) : id(id), name(name) {}
DeviceConfig(DeviceConfig& d) : id(d.id), name(d.name), model(d.model), manufacturer(d.manufacturer), area(d.area), parent(d.parent) {} DeviceConfig(DeviceConfig& d) : id(d.id), name(d.name), model(d.model), manufacturer(d.manufacturer), area(d.area), parent(d.parent) {}
void buildConfig(JsonDocument& jsonDoc) { void buildConfig(JsonDocument& jsonDoc) {
JsonObject device = jsonDoc.createNestedObject("device"); JsonObject device = jsonDoc.createNestedObject("device");
device["name"] = name; if (name) device["name"] = name;
// JsonArray connections = device.createNestedArray("connections");
// JsonArray mac = connections.createNestedArray();
// mac.add("mac");
// mac.add(WiFi.macAddress());
JsonArray identifiers = device.createNestedArray("identifiers");
identifiers.add(id);
if (model) device["model"] = model; if (model) device["model"] = model;
if (manufacturer) device["manufacturer"] = manufacturer; if (manufacturer) device["manufacturer"] = manufacturer;
if (area) device["suggested_area"] = area; if (area) device["suggested_area"] = area;
if (parent) device["via_device"] = parent->id; if (parent) device["via_device"] = parent->id;
JsonArray identifiers = device.createNestedArray("identifiers");
identifiers.add(id);
} }
DeviceConfig* withModel(const char* value) { DeviceConfig* withModel(const char* value) {
@ -58,6 +55,8 @@ namespace Ha {
}; };
struct Component { struct Component {
const char* entityCategory = nullptr;
const char* deviceClass = nullptr;
const char* name = nullptr; const char* name = nullptr;
char* id = nullptr; char* id = nullptr;
const char* type = nullptr; const char* type = nullptr;
@ -66,14 +65,19 @@ namespace Ha {
static List<Component> components; static List<Component> components;
Component(const char* name, const char* id, const char* type) : name(name), id((char*)id), type(type) { Component(const char* name, const char* id, const char* type) : name(name), id((char*)id), type(type) {
sprintf(configTopic, "homeassistant/%s/%s/%s/config", type, MAIN_DEVICE_ID, id);
components.add(this); components.add(this);
} }
virtual void buildUniqueId(char* uniqueId) = 0; virtual void buildUniqueId(char* uniqueId) = 0;
virtual void buildConfig(JsonDocument& jsonDoc) { virtual void buildConfig(JsonDocument& jsonDoc) {
if (String{"diagnostic"}.equals(entityCategory)) {
sprintf(configTopic, "homeassistant/%s/%s/%s_%s/config", type, MAIN_DEVICE_ID, deviceClass, id);
} else {
sprintf(configTopic, "homeassistant/%s/%s/%s/config", type, MAIN_DEVICE_ID, id);
}
if (mainDevice) mainDevice->buildConfig(jsonDoc); if (mainDevice) mainDevice->buildConfig(jsonDoc);
if (entityCategory) jsonDoc["entity_category"] = entityCategory;
jsonDoc["name"] = name; jsonDoc["name"] = name;
char uniqueId[50]; char uniqueId[50];
buildUniqueId(uniqueId); buildUniqueId(uniqueId);
@ -101,6 +105,7 @@ namespace Ha {
mainDevice = new DeviceConfig{*deviceConfig}; mainDevice = new DeviceConfig{*deviceConfig};
mainDevice->id = id; mainDevice->id = id;
mainDevice->name = name; mainDevice->name = name;
mainDevice->parent = deviceConfig->parent;
return static_cast<T*>(this); return static_cast<T*>(this);
} }
}; };
@ -166,23 +171,25 @@ namespace Ha {
}; };
struct Sensor : EntityConfig<Sensor>, StateConfig<Sensor> { struct Sensor : EntityConfig<Sensor>, StateConfig<Sensor> {
const char* deviceClass = nullptr;
const char* unitMeasure = nullptr; const char* unitMeasure = nullptr;
const char* valueTemplate = nullptr; const char* valueTemplate = nullptr;
Sensor(const char* name, const char* id) : EntityConfig(name, id, "sensor") { Sensor(const char* name, const char* id) : EntityConfig(name, Protocol_2::buildId(id), "sensor") {
withStateTopic();
} }
void buildUniqueId(char* uniqueId) override { void buildUniqueId(char* uniqueId) override {
sprintf(uniqueId, "%s", id); sprintf(uniqueId, "%s_%s", deviceClass, id);
} }
void buildConfig(JsonDocument& jsonDoc) override { void buildConfig(JsonDocument& jsonDoc) override {
EntityConfig::buildConfig(jsonDoc); EntityConfig::buildConfig(jsonDoc);
if (entityCategory) jsonDoc["entity_category"] = entityCategory;
jsonDoc["device_class"] = deviceClass; jsonDoc["device_class"] = deviceClass;
jsonDoc["unit_of_measurement"] = unitMeasure; jsonDoc["unit_of_measurement"] = unitMeasure;
jsonDoc["value_template"] = valueTemplate; if (valueTemplate) jsonDoc["value_template"] = valueTemplate;
if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic; jsonDoc["state_topic"] = stateTopic;
jsonDoc["suggested_display_precision"] = 2;
} }
Sensor* withDeviceName(const char* value) { Sensor* withDeviceName(const char* value) {
@ -199,6 +206,24 @@ namespace Ha {
} }
}; };
struct VoltageSensor : Sensor {
VoltageSensor(const char* id, const char* name, const char* valueTemplate) : Sensor(name, id) {
this->valueTemplate = valueTemplate;
entityCategory = "diagnostic";
deviceClass = "voltage";
unitMeasure = "V";
}
};
struct BatterySensor : Sensor {
BatterySensor(const char* id, const char* name, const char* valueTemplate) : Sensor(name, id) {
this->valueTemplate = valueTemplate;
entityCategory = "diagnostic";
deviceClass = "battery";
unitMeasure = "%";
}
};
struct HumiditySensor : Sensor { struct HumiditySensor : Sensor {
HumiditySensor(const char* name, const char* id) : Sensor(name, id) { HumiditySensor(const char* name, const char* id) : Sensor(name, id) {
name = "Humidity"; name = "Humidity";
@ -217,11 +242,11 @@ namespace Ha {
} }
}; };
struct AltitudeSensor : Sensor { // struct AltitudeSensor : Sensor {
AltitudeSensor(const char* name, const char* id) : Sensor(name, id) { // AltitudeSensor(const char* name, const char* id) : Sensor(name, id) {
deviceClass = "distance"; // deviceClass = "distance";
unitMeasure = "m"; // unitMeasure = "m";
valueTemplate = "{{ value_json.sensor.altitude }}"; // valueTemplate = "{{ value_json.sensor.altitude }}";
} // }
}; // };
} }

View File

@ -79,6 +79,13 @@ namespace Board {
} }
} }
} }
if (jsonDoc.containsKey("sensor")) {
JsonObjectConst json = jsonDoc["sensor"];
string id = Protocol_2::buildId((unsigned int)json["id"]);
char stateTopic[TOPIC_SIZE];
sprintf(stateTopic, "homeassistant/sensor/%s/%s/state", MAIN_DEVICE_ID, id.c_str());
Mqtt::publish(stateTopic, message);
}
} }
void handleJsonError(JsonDocument& jsonError) { void handleJsonError(JsonDocument& jsonError) {

View File

@ -32,14 +32,6 @@ namespace Mqtt {
return client.publish(topic, 0, true, message); return client.publish(topic, 0, true, message);
} }
Ha::Sensor* sensors[] = {
(new Ha::TemperatureSensor{"id4"})->withStateTopic()->copyFromDevice(atTinyDevice)->withDeviceName("Oil tank room1")->withArea("Basement")
// new Ha::TemperatureSensor{"Temperature", "temperature"},
// new Ha::HumiditySensor{"Humidity", "humidity"},
// new Ha::PressureSensor{"Pressure", "pressure"},
// new Ha::AltitudeSensor{"Altitude", "altitude"}
};
Ha::Button* buttons[] = { Ha::Button* buttons[] = {
(new Ha::Button{"Restart", "restart", (new Ha::Button{"Restart", "restart",
[](const char* msg) { [](const char* msg) {
@ -57,6 +49,14 @@ namespace Mqtt {
(new EasyHomeSwitch{"Outside", "easy_home_b", (unsigned long[4]) { 4483140, 4626804, 4661556, 4819636 }, (unsigned long[4]) { 4326548, 4537108, 4767524, 4972708 }})->withArea("Basement")->withStateTopic() (new EasyHomeSwitch{"Outside", "easy_home_b", (unsigned long[4]) { 4483140, 4626804, 4661556, 4819636 }, (unsigned long[4]) { 4326548, 4537108, 4767524, 4972708 }})->withArea("Basement")->withStateTopic()
}; };
Ha::Sensor* sensors[] = {
SensorBuilder::withVoltage((new Ha::TemperatureSensor{"4"})->copyFromDevice(atTinyDevice)->withDeviceName("Oil tank room")->withArea("Basement"))
// new Ha::TemperatureSensor{"Temperature", "temperature"},
// new Ha::HumiditySensor{"Humidity", "humidity"},
// new Ha::PressureSensor{"Pressure", "pressure"},
// new Ha::AltitudeSensor{"Altitude", "altitude"}
};
void publishComponentConfig(Ha::Component& component) { void publishComponentConfig(Ha::Component& component) {
StaticJsonDocument<JSON_SIZE> jsonDoc; StaticJsonDocument<JSON_SIZE> jsonDoc;
component.buildConfig(jsonDoc); component.buildConfig(jsonDoc);