Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for setting different prefix for non-discovery topics #29

Merged
merged 5 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ but I successfully use it on ESP8266/ESP8255 boards in my projects.
* [Availability feature](examples/availability)
* [Advanced availability (MQTT LWT)](examples/advanced-availability/advanced-availability.ino)
* [MQTT with credentials](examples/mqtt-with-credentials/mqtt-with-credentials.ino)
* [MQTT events](examples/mqtt-events/mqtt-events.ino)
* [MQTT advanced](examples/mqtt-advanced/mqtt-advanced.ino)

## Tested boards

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ void setup() {
mqtt.onMessage(onMqttMessage);
mqtt.onConnected(onMqttConnected);
mqtt.onConnectionFailed(onMqttConnectionFailed);

// If you use custom discovery prefix you can change it as following:
// mqtt.setDiscoveryPrefix("customPrefix");

// If you want to change prefix only for non-discovery prefix:
// mqtt.setDataPrefix("data");

mqtt.begin(BROKER_ADDR);
}

Expand Down
2 changes: 0 additions & 2 deletions examples/multi-state-button/multi-state-button.ino
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ void setup() {
// you don't need to verify return status
Ethernet.begin(mac);

Serial.println(Ethernet.localIP());

// set device's details (optional)
device.setName("Arduino");
device.setSoftwareVersion("1.0.0");
Expand Down
9 changes: 5 additions & 4 deletions src/HAMqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ HAMqtt::HAMqtt(Client& netClient, HADevice& device) :
_connectionFailedCallback(nullptr),
_initialized(false),
_discoveryPrefix(DefaultDiscoveryPrefix),
_dataPrefix(nullptr),
_mqtt(new PubSubClient(netClient)),
_username(nullptr),
_password(nullptr),
Expand Down Expand Up @@ -196,9 +197,9 @@ bool HAMqtt::publish(const char* topic, const char* payload, bool retained)
}

#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Publishing message with topic: "));
Serial.print(F("Publishing: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(F(", len: "));
Serial.print(strlen(payload));
Serial.println();
#endif
Expand All @@ -215,9 +216,9 @@ bool HAMqtt::beginPublish(
)
{
#if defined(ARDUINOHA_DEBUG)
Serial.print(F("Publishing message with topic: "));
Serial.print(F("Publishing: "));
Serial.print(topic);
Serial.print(F(", payload length: "));
Serial.print(F(", len: "));
Serial.print(payloadLength);
Serial.println();
#endif
Expand Down
18 changes: 18 additions & 0 deletions src/HAMqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class HAMqtt
* Sets prefix for Home Assistant discovery.
* It needs to match prefix set in the HA admin panel.
* The default prefix is "homeassistant".
*
* @param prefix
*/
inline void setDiscoveryPrefix(const char* prefix)
{ _discoveryPrefix = prefix; }
Expand All @@ -36,6 +38,21 @@ class HAMqtt
inline const char* getDiscoveryPrefix() const
{ return _discoveryPrefix; }

/**
* Sets prefix that will be used for topics different than discovery.
* It may be useful if you want to pass MQTT trafic through bridge.
*
* @param prefix
*/
inline void setDataPrefix(const char* prefix)
{ _dataPrefix = prefix; }

/**
* Returns data prefix.
*/
inline const char* getDataPrefix() const
{ return _dataPrefix; }

/**
* Returns instance of the device assigned to the HAMqtt class.
*/
Expand Down Expand Up @@ -211,6 +228,7 @@ class HAMqtt
HAMQTT_CALLBACK(_connectionFailedCallback);
bool _initialized;
const char* _discoveryPrefix;
const char* _dataPrefix;
PubSubClient* _mqtt;
const char* _username;
const char* _password;
Expand Down
7 changes: 5 additions & 2 deletions src/device-types/BaseDeviceType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ void BaseDeviceType::publishConfig()
const uint16_t& topicLength = DeviceTypeSerializer::calculateTopicLength(
componentName(),
name(),
DeviceTypeSerializer::ConfigTopic
DeviceTypeSerializer::ConfigTopic,
true,
true
);
const uint16_t& dataLength = calculateSerializedLength(serializedDevice);

Expand All @@ -74,7 +76,8 @@ void BaseDeviceType::publishConfig()
topic,
componentName(),
name(),
DeviceTypeSerializer::ConfigTopic
DeviceTypeSerializer::ConfigTopic,
true
);

if (strlen(topic) == 0) {
Expand Down
22 changes: 18 additions & 4 deletions src/device-types/DeviceTypeSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,27 @@ const char* DeviceTypeSerializer::Offline = "offline";
const char* DeviceTypeSerializer::StateOn = "ON";
const char* DeviceTypeSerializer::StateOff = "OFF";

const char* DeviceTypeSerializer::getTopicPrefix(bool isDiscoveryTopic)
{
if (!isDiscoveryTopic) {
const char* dataPrefix = HAMqtt::instance()->getDataPrefix();
if (dataPrefix != nullptr) {
return dataPrefix;
}
}

return HAMqtt::instance()->getDiscoveryPrefix();
}

uint16_t DeviceTypeSerializer::calculateTopicLength(
const char* component,
const char* objectId,
const char* suffix,
bool includeNullTerminator
bool includeNullTerminator,
bool isDiscoveryTopic
)
{
const char* prefix = HAMqtt::instance()->getDiscoveryPrefix();
const char* prefix = getTopicPrefix(isDiscoveryTopic);
if (prefix == nullptr) {
return 0;
}
Expand Down Expand Up @@ -58,10 +71,11 @@ uint16_t DeviceTypeSerializer::generateTopic(
char* output,
const char* component,
const char* objectId,
const char* suffix
const char* suffix,
bool isDiscoveryTopic
)
{
const char* prefix = HAMqtt::instance()->getDiscoveryPrefix();
const char* prefix = getTopicPrefix(isDiscoveryTopic);
if (prefix == nullptr) {
return 0;
}
Expand Down
14 changes: 10 additions & 4 deletions src/device-types/DeviceTypeSerializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,44 @@ class DeviceTypeSerializer
static const char* StateOn;
static const char* StateOff;

static const char* getTopicPrefix(bool isDiscoveryTopic);

/**
* Calculates length of the topic with given parameters.
* Topic format: [discovery prefix]/[component]/[deviceId]/[objectId]/[suffix]
* Topic format: [prefix]/[component]/[deviceId]/[objectId]/[suffix]
*
* @param component
* @param objectId
* @param suffix
* @param includeNullTerminator
* @param isDiscoveryTopic Determines which prefix will be used for topic.
*/
static uint16_t calculateTopicLength(
const char* component,
const char* objectId,
const char* suffix,
bool includeNullTerminator = true
bool includeNullTerminator = true,
bool isDiscoveryTopic = false
);

/**
* Generates topic and saves it to the given buffer.
* Please note that size of the buffer must be calculated by `calculateTopicLength` method first.
* Topic format: [discovery prefix]/[component]/[deviceId]/[objectId]/[suffix]
* Topic format: [prefix]/[component]/[deviceId]/[objectId]/[suffix]
*
* @param output
* @param component
* @param objectId
* @param suffix
* @param includeNullTerminator
* @param isDiscoveryTopic Determines which prefix will be used for topic.
*/
static uint16_t generateTopic(
char* output,
const char* component,
const char* objectId,
const char* suffix
const char* suffix,
bool isDiscoveryTopic = false
);

static uint16_t calculateBaseJsonDataSize();
Expand Down
23 changes: 15 additions & 8 deletions src/device-types/HATriggers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ void HATriggers::publishConfig()
const uint16_t& topicLength = calculateTopicLength(
componentName(),
trigger,
DeviceTypeSerializer::ConfigTopic
DeviceTypeSerializer::ConfigTopic,
true,
true
);
const uint16_t& dataLength = calculateSerializedLength(
trigger,
Expand All @@ -147,7 +149,8 @@ void HATriggers::publishConfig()
topic,
componentName(),
trigger,
DeviceTypeSerializer::ConfigTopic
DeviceTypeSerializer::ConfigTopic,
true
);

if (strlen(topic) == 0) {
Expand All @@ -165,27 +168,30 @@ uint16_t HATriggers::calculateTopicLength(
const char* component,
const HATrigger *trigger,
const char* suffix,
bool includeNullTerminator
bool includeNullTerminator,
bool isDiscoveryTopic
) const
{
uint8_t length = strlen(trigger->type) + strlen(trigger->subtype) + 2; // + underscore and slash
uint8_t length = strlen(trigger->type) + strlen(trigger->subtype) + 2; // underscore and slash
return DeviceTypeSerializer::calculateTopicLength(
component,
nullptr,
suffix,
includeNullTerminator
includeNullTerminator,
isDiscoveryTopic
) + length;
}

uint16_t HATriggers::generateTopic(
char* output,
const char* component,
const HATrigger *trigger,
const char* suffix
const char* suffix,
bool isDiscoveryTopic
) const
{
static const char Underscore[] PROGMEM = {"_"};
uint8_t length = strlen(trigger->type) + strlen(trigger->subtype) + 2; // slash + null terminator
uint8_t length = strlen(trigger->type) + strlen(trigger->subtype) + 2; // underscore + null terminator
char objectId[length];

strcpy(objectId, trigger->subtype);
Expand All @@ -196,7 +202,8 @@ uint16_t HATriggers::generateTopic(
output,
component,
objectId,
suffix
suffix,
isDiscoveryTopic
);
}

Expand Down
6 changes: 4 additions & 2 deletions src/device-types/HATriggers.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ class HATriggers : public BaseDeviceType
const char* component,
const HATrigger *trigger,
const char* suffix,
bool includeNullTerminator = true
bool includeNullTerminator = true,
bool isDiscoveryTopic = false
) const;

uint16_t generateTopic(
char* output,
const char* component,
const HATrigger *trigger,
const char* suffix
const char* suffix,
bool isDiscoveryTopic = false
) const;

private:
Expand Down