mirror of
https://github.com/mrcory/arduino-home-assistant.git
synced 2026-08-02 15:24:26 -04:00
handle HASwitch subscription messages
This commit is contained in:
+1
-1
@@ -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
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef HAUTILS_H
|
||||
#define HAUTILS_H
|
||||
|
||||
class HAUtils
|
||||
{
|
||||
public:
|
||||
static bool endsWith(const char *str, const char *suffix);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user