finished HATriggers

This commit is contained in:
Dawid Chyrzynski
2020-12-02 21:55:49 +01:00
parent 070a437284
commit eb5667512c
2 changed files with 238 additions and 0 deletions
+197
View File
@@ -0,0 +1,197 @@
#include <Arduino.h>
#include "HATriggers.h"
#include "../ArduinoHADefines.h"
#include "../HAMqtt.h"
#include "../HADevice.h"
const char* HATriggers::MqttNamespace = "device_automation";
HATriggers::HATriggers(HAMqtt& mqtt) :
BaseDeviceType(nullptr, mqtt),
_triggers(nullptr),
_triggersNb(0)
{
#if defined(ARDUINOHA_DEBUG)
if (mqtt.getDevice() == nullptr) {
Serial.println(F("HATriggers requires HADevice to be defined."));
}
#endif
}
HATriggers::~HATriggers()
{
free(_triggers);
}
void HATriggers::onMqttConnected()
{
const HADevice* device = mqtt()->getDevice();
uint16_t deviceLength = (device == nullptr ? 0 : device->calculateSerializedLength());
char serializedDevice[deviceLength];
if (device != nullptr) {
device->serialize(serializedDevice);
}
for (uint8_t i = 0; i < _triggersNb; i++) {
const HATrigger* trigger = &_triggers[i];
const uint16_t& topicLength = calculateTopicLength(MqttNamespace, trigger->type, trigger->subtype, ConfigTopic);
const uint16_t& dataLength = calculateSerializedLength(trigger, serializedDevice);
char topic[topicLength];
char data[dataLength];
generateTopic(topic, MqttNamespace, trigger->type, trigger->subtype, ConfigTopic);
if (mqtt()->beginPublish(topic, dataLength, true)) {
writeSerializedTrigger(trigger, serializedDevice);
mqtt()->endPublish();
}
}
}
bool HATriggers::add(const char* type, const char* subtype)
{
if (mqtt()->getDevice() == nullptr) {
return false; // device is required for triggers
}
HATrigger* triggers = realloc(_triggers, sizeof(HATrigger) * (_triggersNb + 1));
if (triggers == nullptr) {
return false;
}
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Adding HATrigger: "));
Serial.print(type);
Serial.print(F(" "));
Serial.print(subtype);
Serial.println();
#endif
_triggers = triggers;
_triggers[_triggersNb].type = type;
_triggers[_triggersNb].subtype = subtype;
_triggersNb++;
return true;
}
bool HATriggers::trigger(const char* type, const char* subtype)
{
bool found = false;
for (uint8_t i = 0; i < _triggersNb; i++) {
const HATrigger* trigger = &_triggers[i];
if (strcmp(trigger->type, type) == 0 &&
strcmp(trigger->subtype, subtype) == 0) {
found = true;
break;
}
}
if (!found) {
return false;
}
const uint16_t& size = calculateTopicLength(MqttNamespace, type, subtype, EventTopic);
char topic[size];
generateTopic(topic, MqttNamespace, type, subtype, EventTopic);
mqtt()->publish(topic, "");
}
uint16_t HATriggers::calculateSerializedLength(
const HATrigger* trigger,
const char* serializedDevice
) const
{
const uint16_t& topicLength = calculateTopicLength(
MqttNamespace,
trigger->type,
trigger->subtype,
EventTopic,
false
);
uint16_t size =
2 + // opening and closing bracket (without null terminator)
17 + // automation type
topicLength + 7 +
strlen(trigger->type) + 10 +
strlen(trigger->subtype) + 11;
if (serializedDevice != nullptr) {
size += strlen(serializedDevice) + 7;
}
return size;
}
bool HATriggers::writeSerializedTrigger(
const HATrigger* trigger,
const char* serializedDevice
) const
{
// automation type
{
static const char Data[] = "{\"atype\":\"trigger\"";
mqtt()->writePayload(Data, strlen(Data));
}
// topic
{
const uint16_t& topicSize = calculateTopicLength(
MqttNamespace,
trigger->type,
trigger->subtype,
EventTopic
);
char eventTopic[topicSize];
generateTopic(eventTopic,
MqttNamespace,
trigger->type,
trigger->subtype,
EventTopic
);
static const char DataBefore[] = ",\"t\":\"";
static const char DataAfter[] = "\"";
mqtt()->writePayload(DataBefore, strlen(DataBefore));
mqtt()->writePayload(eventTopic, strlen(eventTopic));
mqtt()->writePayload(DataAfter, strlen(DataAfter));
}
// type
{
static const char DataBefore[] = ",\"type\":\"";
static const char DataAfter[] = "\"";
mqtt()->writePayload(DataBefore, strlen(DataBefore));
mqtt()->writePayload(trigger->type, strlen(trigger->type));
mqtt()->writePayload(DataAfter, strlen(DataAfter));
}
// subtype
{
static const char DataBefore[] = ",\"stype\":\"";
static const char DataAfter[] = "\"";
mqtt()->writePayload(DataBefore, strlen(DataBefore));
mqtt()->writePayload(trigger->subtype, strlen(trigger->subtype));
mqtt()->writePayload(DataAfter, strlen(DataAfter));
}
// device
if (serializedDevice != nullptr) {
static const char Data[] = ",\"dev\":";
mqtt()->writePayload(Data, strlen(Data));
mqtt()->writePayload(serializedDevice, strlen(serializedDevice));
}
{
static const char Data[] = "}";
mqtt()->writePayload(Data, strlen(Data));
}
return true;
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef HATRIGGERS_H
#define HATRIGGERS_H
#include <stdint.h>
#include "BaseDeviceType.h"
struct HATrigger {
const char* type;
const char* subtype;
} __attribute__((packed));
class HATriggers : public BaseDeviceType
{
public:
static const char* MqttNamespace;
HATriggers(HAMqtt& mqtt);
virtual ~HATriggers();
virtual void onMqttConnected() override;
bool add(const char* type, const char* subtype);
bool trigger(const char* type, const char* subtype);
private:
uint16_t calculateSerializedLength(
const HATrigger* trigger,
const char* serializedDevice
) const;
bool writeSerializedTrigger(
const HATrigger* trigger,
const char* serializedDevice
) const;
HATrigger* _triggers;
uint8_t _triggersNb;
};
#endif