Skip to content

Commit

Permalink
Add more Home Assistant support.
Browse files Browse the repository at this point in the history
Reanmed all entities in Home Assistant
  • Loading branch information
bergdahl committed Nov 28, 2023
1 parent f7476cd commit 3607817
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 37 deletions.
13 changes: 9 additions & 4 deletions src/jbwopr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ void JBWoprDevice::effectsStartEffect(JBWoprEffectBase* effect) {
_currentEffect->start();
}

void JBWoprDevice::effectsStartEffect(std::string name) {
void JBWoprDevice::effectsStartEffect(const std::string& name) {
for (const auto& effect : _effects) {
if (effect->getName() == name) {
effectsStartEffect(effect);
Expand Down Expand Up @@ -420,12 +420,17 @@ Adafruit_NeoPixel* JBWoprDevice::getDefconLeds() {
void JBWoprDevice::defconLedsSetState(bool state) {
_defconState = state;
_defconLeds.setBrightness(state ? _defconBrigthtness : 0);
for (int i = 0; i < 5; i++) {
_defconLeds.setPixelColor(i, _defconPixels[i]);
}
_defconLeds.show();
}

void JBWoprDevice::defconLedsSetDefconLevel(JBDefconLevel level) {
_log->trace("defconLedsSetDefconLevel %s", _getDefconLevelString(level).c_str());
_defconLevel = level;
uint32_t led = _getDefconLedsPixel(level);
_defconLeds.setBrightness(_defconState ? _defconBrigthtness : 0);
for (uint32_t i = 0; i < 5; i++) {
if (i == led) {
_defconPixels[i] = _defconColors[int(level)];
Expand All @@ -436,29 +441,29 @@ void JBWoprDevice::defconLedsSetDefconLevel(JBDefconLevel level) {
_defconLeds.setPixelColor(i, 0);
}
}
_defconLeds.setBrightness(_defconState ? _defconBrigthtness : 0);
_defconLeds.show();
}

void JBWoprDevice::defconLedsSetColor(uint32_t color)
{
_log->trace("defconLedsSetColor %s", JBStringHelper::rgbToString(color).c_str());
_defconLedsColor = color;
_defconLeds.setBrightness(_defconState ? _defconBrigthtness : 0);
for (int i = 0; i < 5; i++) {
_defconPixels[i] = color;
_defconLeds.setPixelColor(i, color);
}
_defconLeds.setBrightness(_defconState ? _defconBrigthtness : 0);
_defconLeds.show();
}

void JBWoprDevice::defconLedsSetBrightness(uint8_t brightness) {
_log->trace("defconLedsSetBrightness %i", brightness);
brightness = constrain(brightness, 0, 100);
_defconBrightness = map(brightness, 0, 100, 0, 255);
_defconLeds.setBrightness(_defconState ? _defconBrightness : 0);
for (int i = 0; i < 5; i++) {
_defconLeds.setPixelColor(i, _defconPixels[i]);
}
_defconLeds.setBrightness(_defconState ? _defconBrightness : 0);
_defconLeds.show();
}

Expand Down
18 changes: 10 additions & 8 deletions src/jbwopr.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ class JBWoprDevice {

/// @brief Start current effect
/// @ingroup EffectsGroup
void effectsStartCurrentEffect();
virtual void effectsStartCurrentEffect();

/// @brief Stop current effect
/// @ingroup EffectsGroup
void effectsStopCurrentEffect();
virtual void effectsStopCurrentEffect();

/// @brief Check if current effect is running
/// @ingroup EffectsGroup
Expand All @@ -188,7 +188,7 @@ class JBWoprDevice {
/// @brief Start named effect
/// @ingroup EffectsGroup
/// @param name Name of effect to start
virtual void effectsStartEffect(std::string name);
virtual void effectsStartEffect(const std::string& name);

/// @brief Start named effect
/// @ingroup EffectsGroup
Expand Down Expand Up @@ -320,6 +320,11 @@ class JBWoprDevice {
/// @param state True to turn DEFCON LEDs on, false to turn them off
virtual void defconLedsSetState(bool state);

/// @brief Set DEFCON LED's brightness level
/// @ingroup DefconGroup
/// @param brightness Brightness value, 0 - 100
virtual void defconLedsSetBrightness(uint8_t brightness);

/// @brief Set DEFCON level
/// @ingroup DefconGroup
/// @param level DEFCON level
Expand All @@ -330,11 +335,6 @@ class JBWoprDevice {
/// @param color Color value
virtual void defconLedsSetColor(uint32_t color);

/// @brief Set DEFCON LED's brightness level
/// @ingroup DefconGroup
/// @param brightness Brightness value, 0 - 100
virtual void defconLedsSetBrightness(uint8_t brightness);

/// @brief Clear all DEFCON LEDs
/// @ingroup DefconGroup
virtual void defconLedsClear();
Expand Down Expand Up @@ -472,8 +472,10 @@ class JBWoprDevice {
//
Adafruit_NeoPixel _defconLeds = Adafruit_NeoPixel(5, 1, NEO_GRB + NEO_KHZ800); ///< DEFCON LEDs
bool _defconState = true; ///< DEFCON state
JBDefconLevel _defconLevel = JBDefconLevel::DEFCON_NONE; ///< DEFCON level
uint32_t _defconColors[5]; ///< DEFCON colors
uint32_t _defconBrightness = 100; ///< DEFCON brightness
uint32_t _defconLedsColor = 0; ///< DEFCON LED's color

// Note - due to how Adafruit_Neopixel handles brigthness, we buffer the LED colors into the
// _defconPixels variable together with the current brightness value.
Expand Down
73 changes: 48 additions & 25 deletions src/jbwoprha.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
jsonDoc["name"] = "Restart";
_addDeviceData(jsonDoc);
jsonDoc[HA_NAMES_ENTITY_CATEGORY] = HA_CONFIG_PREFIX;
jsonDoc["unique_id"] = "device";
jsonDoc["object_id"] = "device";
jsonDoc["unique_id"] = _getDeviceName() + "_" +"device";
jsonDoc["object_id"] = _getDeviceName() + "_" +"device";
_addAvailabilityData(jsonDoc);
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/device/state/set";
jsonDoc["payload_press"] = "restart";
Expand All @@ -297,15 +297,30 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
// Effects
{
DynamicJsonDocument jsonDoc(1024);
topic = "homeassistant/select/" + _getDeviceName() + "/effect/config";
jsonDoc["name"] = "Effect";
topic = "homeassistant/switch/" + _getDeviceName() + "/effect/config";
jsonDoc["name"] = "Run effect";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = "effect";
jsonDoc["object_id"] = "effect";
jsonDoc["unique_id"] = _getDeviceName() + "_" + "effect";
jsonDoc["object_id"] = _getDeviceName() + "_" + "effect";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/effect/state";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/effect/state/set";
auto effects = effectsGetRegisteredEffects();
jsonDoc["icon"] = MDI_ICON_SCRIPT_OUTLINE;
mqttPublishMessage(topic, jsonDoc, true);
}

{
DynamicJsonDocument jsonDoc(1024);
topic = "homeassistant/select/" + _getDeviceName() + "/effect/config";
jsonDoc["name"] = "Effect";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = _getDeviceName() + "_effect";
jsonDoc["object_id"] = _getDeviceName() + "_effect";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/effect/name";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/effect/name/set";
auto effects = effectsGetRegisteredEffects();
auto options = jsonDoc.createNestedArray("options");
options.add("");
for (auto& effect : effects) {
Expand All @@ -321,8 +336,8 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
topic = "homeassistant/light/" + _getDeviceName() + "/display/config";
jsonDoc["name"] = "Display";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = "display";
jsonDoc["object_id"] = "display";
jsonDoc["unique_id"] = _getDeviceName() + "_display";
jsonDoc["object_id"] = _getDeviceName() + "_display";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/display/state";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/display/state/set";
Expand All @@ -338,8 +353,8 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
topic = "homeassistant/light/" + _getDeviceName() + "/defcon/config";
jsonDoc["name"] = "DEFCON";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = "defcon";
jsonDoc["object_id"] = "defcon";
jsonDoc["unique_id"] = _getDeviceName() + "_defcon";
jsonDoc["object_id"] = _getDeviceName() + "_defcon";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/defcon/state";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/defcon/state/set";
Expand All @@ -356,18 +371,15 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
topic = "homeassistant/select/" + _getDeviceName() + "/defcon_level/config";
jsonDoc["name"] = "DEFCON Level";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = "defcon_level";
jsonDoc["object_id"] = "defcon_level";
jsonDoc["unique_id"] = _getDeviceName() + "_defcon_level";
jsonDoc["object_id"] = _getDeviceName() + "_defcon_level";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/defcon/level";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/defcon/level/set";
auto options = jsonDoc.createNestedArray("options");
options.add("None");
options.add("DEFCON 5");
options.add("DEFCON 4");
options.add("DEFCON 3");
options.add("DEFCON 2");
options.add("DEFCON 1");
for (auto& level : _defconNames) {
options.add(level);
}
jsonDoc["icon"] = MDI_ICON_NUMERIC_5_BOX_OUTLINE;
mqttPublishMessage(topic, jsonDoc, true);
}
Expand All @@ -377,8 +389,8 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
topic = "homeassistant/text/" + _getDeviceName() + "/display_text/config";
jsonDoc["name"] = "Display text";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = "display_text";
jsonDoc["object_id"] = "display_text";
jsonDoc["unique_id"] = _getDeviceName() + "_display_text";
jsonDoc["object_id"] = _getDeviceName() + "_display_text";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/display/text";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/display/text/set";
Expand All @@ -391,8 +403,8 @@ bool JBWoprHADevice::_homeAssistantSendDiscovery() {
topic = "homeassistant/text/" + _getDeviceName() + "/display_scrolltext/config";
jsonDoc["name"] = "Display scroll text";
_addDeviceData(jsonDoc);
jsonDoc["unique_id"] = "display_scrolltext";
jsonDoc["object_id"] = "display_scrolltext";
jsonDoc["unique_id"] = _getDeviceName() + "_display_scrolltext";
jsonDoc["object_id"] = _getDeviceName() + "_display_scrolltext";
_addAvailabilityData(jsonDoc);
jsonDoc["state_topic"] = "wopr/" + _getDeviceName() + "/display/scrolltext";
jsonDoc["command_topic"] = "wopr/" + _getDeviceName() + "/display/scrolltext/set";
Expand Down Expand Up @@ -436,8 +448,19 @@ bool JBWoprHADevice::_homeAssistantPublishConfig() {
bool JBWoprHADevice::_homeAssistantPublishState() {
_log->trace("Publishing Home Assistant state messages");

// Effect
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), effectsCurrentEffectIsRunning() ? "ON" : "OFF");
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_NAME), "");
// Display
//auto displayStateTopic = _getDiscoveryTopic("light", "display");
mqttPublishMessage(_getTopic(ENTITY_NAME_DISPLAY, SUBENTITY_NAME_STATE), _displayState ? "ON" : "OFF" );
mqttPublishMessage(_getTopic(ENTITY_NAME_DISPLAY, SUBENTITY_NAME_TEXT), "");
mqttPublishMessage(_getTopic(ENTITY_NAME_DISPLAY, SUBENTITY_NAME_BRIGHTNESS), std::to_string(_displayBrightness));
mqttPublishMessage(_getTopic(ENTITY_NAME_DISPLAY, SUBENTITY_NAME_SCROLLTEXT), "");
// DEFCON
mqttPublishMessage(_getTopic(ENTITY_NAME_DEFCON, SUBENTITY_NAME_STATE), _defconState ? "ON" : "OFF");
mqttPublishMessage(_getTopic(ENTITY_NAME_DEFCON, SUBENTITY_NAME_LEVEL), _defconNames.at((uint32_t)_defconLevel));
mqttPublishMessage(_getTopic(ENTITY_NAME_DEFCON, SUBENTITY_NAME_BRIGHTNESS), std::to_string(_defconBrightness));
mqttPublishMessage(_getTopic(ENTITY_NAME_DEFCON, SUBENTITY_NAME_COLOR), JBStringHelper::rgbToString(_defconLedsColor));

_log->error("HA State not implemented");
return false;
Expand Down Expand Up @@ -467,8 +490,8 @@ void JBWoprHADevice::_addDiscoveryPayload(DynamicJsonDocument& jsonDoc,
if (!prefix.empty()) {
jsonDoc[HA_NAMES_ENTITY_CATEGORY] = prefix;
}
jsonDoc[HA_NAMES_UNIQUE_ID] = prefix + "_" + entity;
jsonDoc[HA_NAMES_OBJECT_ID] = prefix + "_" + entity;
jsonDoc[HA_NAMES_UNIQUE_ID] = _getDeviceName() + "_" + prefix + "_" + entity;
jsonDoc[HA_NAMES_OBJECT_ID] = _getDeviceName() + "_" +prefix + "_" + entity;
jsonDoc[HA_NAMES_STATE_TOPIC] = _getTopic(prefix, SUBENTITY_NAME_STATE);
jsonDoc[HA_NAMES_VALUE_TEMPLATE] = "{{ value_json." + valueTemplate + "}}";
if (!icon.empty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/jbwoprha.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ class JBWoprHADevice: public JBWoprMqttDevice {
const char* JSON_KEY_HA_DIAG_ENTITY_RAM = "ram"; ///< RAM entity key name
const char* JSON_KEY_HA_DIAG_ENTITY_VERSION = "version"; ///< Version entity key name

const std::vector<std::string> _defconNames { "None", "DEFCON 5", "DEFCON 4", "DEFCON 3", "DEFCON 2", "DEFCON 1" }; ///< DEFCON names

/// @brief Send Home Assistant discovery
bool _homeAssistantSendDiscovery();

Expand Down
37 changes: 37 additions & 0 deletions src/jbwoprmqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ bool JBWoprMqttDevice::begin(JBWoprBoardVariant variant, JBWoprBoardPins pins)
}

void JBWoprMqttDevice::loop() {
if (!effectsCurrentEffectIsRunning() && _effectsCounter == 0) {
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), STATE_OFF);
}

JBWoprWiFiDevice::loop();

if (_mqttActive) {
Expand Down Expand Up @@ -112,6 +116,37 @@ bool JBWoprMqttDevice::mqttPublishMessage(const char* configTopic, const char* v
return true;
}

// ====================================================================
// Effects
//
void JBWoprMqttDevice::effectsStartCurrentEffect() {
JBWoprWiFiDevice::effectsStartCurrentEffect();
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), STATE_ON);
}

void JBWoprMqttDevice::effectsStopCurrentEffect() {
JBWoprWiFiDevice::effectsStopCurrentEffect();
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), STATE_OFF);
}

void JBWoprMqttDevice::effectsStartEffect(JBWoprEffectBase *effect) {
JBWoprWiFiDevice::effectsStartEffect(effect);
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_NAME), effect->getName());
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), STATE_ON);
}

void JBWoprMqttDevice::effectsStartEffect(const std::string& effect) {
JBWoprWiFiDevice::effectsStartEffect(effect);
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_NAME), effect);
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), STATE_ON);
}

void JBWoprMqttDevice::effectsStartEffect(const char* effect) {
JBWoprWiFiDevice::effectsStartEffect(effect);
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_NAME), effect);
mqttPublishMessage(_getTopic(ENTITY_NAME_EFFECT, SUBENTITY_NAME_STATE), STATE_ON);
}

// ====================================================================
// Display
//
Expand Down Expand Up @@ -667,3 +702,5 @@ void JBWoprMqttDevice::_buttonBackBottomDoubleClick()





30 changes: 30 additions & 0 deletions src/jbwoprmqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <PubSubClient.h> // https://github.com/knolleary/pubsubclient
#include <WiFiManager.h>
#include <JBLogger.h>
#include "effects/jbwopreffects.h"

#define DEFAULT_MQTT_PREFIX "wopr" ///< Default MQTT prefix
#define DEFAULT_MQTT_PORT 1883 ///< Default MQTT port
Expand Down Expand Up @@ -107,6 +108,35 @@ class JBWoprMqttDevice: public JBWoprWiFiDevice {
/// @return True if successful
bool mqttPublishMessage(const char* topic, const char* value, bool retain = false);

// ====================================================================
// Effects
//
/// @brief Effects start current effect
/// @ingroup EffectsGroup
void effectsStartCurrentEffect() override;

/// @brief Stop current effect
/// @ingroup EffectsGroup
virtual void effectsStopCurrentEffect();

/// @brief Effects start effect
/// @ingroup EffectsGroup
/// @details This method will start the specified effect.
/// @param effect Effect
void effectsStartEffect(JBWoprEffectBase* effect) override;

/// @brief Effects start effect
/// @ingroup EffectsGroup
/// @details This method will start the name effect.
/// @param effect Effect name
void effectsStartEffect(const std::string& effect) override;

/// @brief Effects start effect
/// @ingroup EffectsGroup
/// @details This method will start the named effect.
/// @param effect Effect name
void effectsStartEffect(const char* effect) override;

// ====================================================================
// Display
//
Expand Down

0 comments on commit 3607817

Please sign in to comment.