handle HASwitch subscription messages

This commit is contained in:
Dawid Chyrzynski
2020-12-03 21:40:15 +01:00
parent 81935bd898
commit a311ab047b
9 changed files with 133 additions and 45 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ version=1.0.0
author=Dawid Chyrzynski <dawid.chyrzynski@gmail.com>
maintainer=Dawid Chyrzynski <dawid.chyrzynski@gmail.com>
sentence=Home Assistant MQTT integration for Arduino
paragraph=This library provides easy to use API for integrating your Arduin-based device with Home Assistant.
paragraph=Lightweight library that provides easy to use API for integrating your Arduin-based device with Home Assistant.
category=Communication
url=https://github.com/dawidchyrzynski/arduino-home-assistant
architectures=avr
+49 -29
View File
@@ -19,10 +19,15 @@
_devicesTypes(nullptr)
const char* HAMqtt::DefaultDiscoveryPrefix = "homeassistant";
HAMqtt* instance = nullptr;
void onMessageReceived(char* topic, char* message, uint32_t length)
void onMessageReceived(char* topic, uint8_t* payload, uint16_t length)
{
// todo: process message
if (instance == nullptr) {
return;
}
instance->processMessage(topic, payload, length);
}
HAMqtt::HAMqtt(const char* clientId, Client& netClient) :
@@ -31,7 +36,7 @@ HAMqtt::HAMqtt(const char* clientId, Client& netClient) :
_hasDevice(false),
HAMQTT_INIT
{
instance = this;
}
HAMqtt::HAMqtt(const char* clientId, Client& netClient, HADevice& device) :
@@ -41,7 +46,7 @@ HAMqtt::HAMqtt(const char* clientId, Client& netClient, HADevice& device) :
_hasDevice(true),
HAMQTT_INIT
{
instance = this;
}
bool HAMqtt::begin(
@@ -108,7 +113,7 @@ void HAMqtt::addDeviceType(BaseDeviceType* deviceType)
void HAMqtt::removeDeviceType(BaseDeviceType* deviceType)
{
// to do
// todo: remove device from the list
}
bool HAMqtt::publish(const char* topic, const char* payload, bool retained)
@@ -117,13 +122,13 @@ bool HAMqtt::publish(const char* topic, const char* payload, bool retained)
return false;
}
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Publishing message with topic: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(strlen(payload));
Serial.println();
#endif
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Publishing message with topic: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(strlen(payload));
Serial.println();
#endif
_mqtt->beginPublish(topic, strlen(payload), retained);
_mqtt->write(payload, strlen(payload));
@@ -136,13 +141,13 @@ bool HAMqtt::beginPublish(
bool retained
)
{
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Publishing message with topic: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(payloadLength);
Serial.println();
#endif
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Publishing message with topic: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(payloadLength);
Serial.println();
#endif
return _mqtt->beginPublish(topic, payloadLength, retained);
}
@@ -167,15 +172,30 @@ bool HAMqtt::endPublish()
bool HAMqtt::subscribe(const char* topic)
{
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Subscribing topic: "));
Serial.print(topic);
Serial.println();
#endif
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Subscribing topic: "));
Serial.print(topic);
Serial.println();
#endif
return _mqtt->subscribe(topic);
}
void HAMqtt::processMessage(char* topic, uint8_t* payload, uint16_t length)
{
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Received message on topic: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(length);
Serial.println();
#endif
for (uint8_t i = 0; i < _devicesTypesNb; i++) {
_devicesTypes[i]->onMqttMessage(topic, payload, length);
}
}
void HAMqtt::connectToServer()
{
if (_lastConnectionAttemptAt > 0 &&
@@ -185,11 +205,11 @@ void HAMqtt::connectToServer()
_lastConnectionAttemptAt = millis();
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Connecting to the MQTT broker... Client ID: "));
Serial.print(_clientId);
Serial.println();
#endif
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Connecting to the MQTT broker... Client ID: "));
Serial.print(_clientId);
Serial.println();
#endif
if (_username == nullptr || _password == nullptr) {
_mqtt->connect(_clientId);
+1
View File
@@ -95,6 +95,7 @@ public:
bool writePayload_P(const char* src);
bool endPublish();
bool subscribe(const char* topic);
void processMessage(char* topic, uint8_t* payload, uint16_t length);
private:
/**
+19
View File
@@ -0,0 +1,19 @@
#include <Arduino.h>
#include "HAUtils.h"
bool HAUtils::endsWith(const char *str, const char *suffix)
{
if (str == nullptr || suffix == nullptr) {
return false;
}
uint16_t lenstr = strlen(str);
uint16_t lensuffix = strlen(suffix);
if (lensuffix > lenstr) {
return false;
}
return (strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0);
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef HAUTILS_H
#define HAUTILS_H
class HAUtils
{
public:
static bool endsWith(const char *str, const char *suffix);
};
#endif
+5 -2
View File
@@ -15,8 +15,11 @@ public:
virtual ~BaseDeviceType();
virtual void onMqttConnected() = 0;
// to do: onMqttMessage
virtual void onMqttMessage(
const char* topic,
const char* payload,
const uint16_t& length
) { };
protected:
inline HAMqtt* mqtt() const
+34 -8
View File
@@ -4,6 +4,7 @@
#include "../ArduinoHADefines.h"
#include "../HAMqtt.h"
#include "../HADevice.h"
#include "../HAUtils.h"
// todo: move all variables to progmem
static const char* HAComponentName = "switch";
@@ -12,11 +13,11 @@ static const char* StateTopic = "state";
static const char* StateOn = "ON";
static const char* StateOff = "OFF";
HASwitch::HASwitch(const char* name, HAMqtt& mqtt) :
HASwitch::HASwitch(const char* name, bool initialState, HAMqtt& mqtt) :
BaseDeviceType(mqtt),
_name(name),
_stateCallback(nullptr),
_currentState(false)
_currentState(initialState)
{
}
@@ -33,9 +34,33 @@ void HASwitch::onMqttConnected()
}
publishConfig();
publishCurrentState();
subscribeCommandTopic();
}
void HASwitch::onMqttMessage(
const char* topic,
const char* payload,
const uint16_t& length
)
{
// todo: find a faster way of topic's verification
static const char Slash[] PROGMEM = {"/"};
uint8_t suffixLength = strlen(_name) + strlen(CommandTopic) + 3; // two slashes + null terminator
char suffix[suffixLength];
strcpy_P(suffix, Slash);
strcat(suffix, _name);
strcat_P(suffix, Slash);
strcat(suffix, CommandTopic);
if (HAUtils::endsWith(topic, suffix)) {
bool onState = (strncmp(payload, StateOn, length) == 0);
setState(onState);
}
}
void HASwitch::setState(bool state)
{
if (state) {
@@ -156,18 +181,19 @@ uint16_t HASwitch::calculateSerializedLength(const char* serializedDevice) const
uint16_t size =
2 + // opening and closing bracket (without null terminator)
cmdTopicLength + 10 +
stateTopicLength + 12 +
strlen(_name) + 10;
cmdTopicLength + 10 + // 10 - length of the JSON data for this field
stateTopicLength + 12 + // 12 - length of the JSON data for this field
strlen(_name) + 10; // 10 - length of the JSON data for this field
// unique ID
if (serializedDevice == nullptr) {
size += strlen(_name) + 13;
size += strlen(_name) + 13; // 13 - length of the JSON data for this field
} else {
size += strlen(mqtt()->getDevice()->getUniqueId()) + strlen(_name) + 14;
size += strlen(mqtt()->getDevice()->getUniqueId());
size += strlen(_name) + 14; // 14 - length of the JSON data for this field
// device
size += strlen(serializedDevice) + 7;
size += strlen(serializedDevice) + 7; // 7 - length of the JSON data for this field
}
return size;
+10 -1
View File
@@ -9,10 +9,19 @@
class HASwitch : public BaseDeviceType
{
public:
HASwitch(const char* name, HAMqtt& mqtt);
HASwitch(
const char* name,
bool initialState,
HAMqtt& mqtt
);
virtual ~HASwitch();
virtual void onMqttConnected() override;
virtual void onMqttMessage(
const char* topic,
const char* payload,
const uint16_t& length
) override;
void setState(bool state);
void turnOn();
+4 -4
View File
@@ -159,12 +159,12 @@ uint16_t HATriggers::calculateSerializedLength(
uint16_t size =
2 + // opening and closing bracket (without null terminator)
17 + // automation type
topicLength + 7 +
strlen(trigger->type) + 10 +
strlen(trigger->subtype) + 11;
topicLength + 7 + // 7 - length of the JSON data for this field
strlen(trigger->type) + 10 + // 10 - length of the JSON data for this field
strlen(trigger->subtype) + 11; // 11 - length of the JSON data for this field
if (serializedDevice != nullptr) {
size += strlen(serializedDevice) + 7;
size += strlen(serializedDevice) + 7; // 7 - length of the JSON data for this field
}
return size;