Skip to content
Open
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
125 changes: 124 additions & 1 deletion docs/documents/api/device-types/ha-light.html

Large diffs are not rendered by default.

28 changes: 26 additions & 2 deletions docs/genindex.html
Original file line number Diff line number Diff line change
Expand Up @@ -892,23 +892,29 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight18_currentBrightnessE">HALight::_currentBrightness (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight24_currentColorTemperatureE">HALight::_currentColorTemperature (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight14_currentEffectE">HALight::_currentEffect (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight16_currentRGBColorE">HALight::_currentRGBColor (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight13_currentStateE">HALight::_currentState (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight15_effectCallbackE">HALight::_effectCallback (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight8_effectsE">HALight::_effects (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight9_featuresE">HALight::_features (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight5_iconE">HALight::_icon (C++ member)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight10_maxMiredsE">HALight::_maxMireds (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight10_minMiredsE">HALight::_minMireds (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight11_optimisticE">HALight::_optimistic (C++ member)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight7_retainE">HALight::_retain (C++ member)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight17_rgbColorCallbackE">HALight::_rgbColorCallback (C++ member)</a>
Expand All @@ -924,12 +930,16 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight8Features23ColorTemperatureFeatureE">HALight::Features::ColorTemperatureFeature (C++ enumerator)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight8Features15DefaultFeaturesE">HALight::Features::DefaultFeatures (C++ enumerator)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight8Features14EffectsFeatureE">HALight::Features::EffectsFeature (C++ enumerator)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight8Features10RGBFeatureE">HALight::Features::RGBFeature (C++ enumerator)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4NK7HALight20getCurrentBrightnessEv">HALight::getCurrentBrightness (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4NK7HALight26getCurrentColorTemperatureEv">HALight::getCurrentColorTemperature (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4NK7HALight16getCurrentEffectEv">HALight::getCurrentEffect (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4NK7HALight18getCurrentRGBColorEv">HALight::getCurrentRGBColor (C++ function)</a>
</li>
Expand All @@ -940,6 +950,8 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight23handleBrightnessCommandEPK7uint8_tK8uint16_t">HALight::handleBrightnessCommand (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight29handleColorTemperatureCommandEPK7uint8_tK8uint16_t">HALight::handleColorTemperatureCommand (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight19handleEffectCommandEPK7uint8_tK8uint16_t">HALight::handleEffectCommand (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight16handleRGBCommandEPK7uint8_tK8uint16_t">HALight::handleRGBCommand (C++ function)</a>
</li>
Expand All @@ -948,6 +960,8 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight19onBrightnessCommandEPFv7uint8_tP7HALightE">HALight::onBrightnessCommand (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight25onColorTemperatureCommandEPFv8uint16_tP7HALightE">HALight::onColorTemperatureCommand (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight15onEffectCommandEPFv7uint8_tP7HALightE">HALight::onEffectCommand (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight15onMqttConnectedEv">HALight::onMqttConnected (C++ function)</a>
</li>
Expand All @@ -960,6 +974,8 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight17publishBrightnessEK7uint8_t">HALight::publishBrightness (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight23publishColorTemperatureEK8uint16_t">HALight::publishColorTemperature (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight13publishEffectEK7uint8_t">HALight::publishEffect (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight15publishRGBColorERK8RGBColor">HALight::publishRGBColor (C++ function)</a>
</li>
Expand Down Expand Up @@ -996,10 +1012,16 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight20setCurrentBrightnessEK7uint8_t">HALight::setCurrentBrightness (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight26setCurrentColorTemperatureEK8uint16_t">HALight::setCurrentColorTemperature (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight16setCurrentEffectEK7uint8_t">HALight::setCurrentEffect (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight18setCurrentRGBColorERK8RGBColor">HALight::setCurrentRGBColor (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight15setCurrentStateEKb">HALight::setCurrentState (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight9setEffectEK7uint8_tKb">HALight::setEffect (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight10setEffectsEA_PCKcK7uint8_t">HALight::setEffects (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight7setIconEPKc">HALight::setIcon (C++ function)</a>
</li>
Expand All @@ -1018,6 +1040,8 @@ <h2 id="H">H</h2>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight7turnOffEv">HALight::turnOff (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALight6turnOnEv">HALight::turnOn (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-light.html#_CPPv4N7HALightD0Ev">HALight::~HALight (C++ function)</a>
</li>
<li><a href="documents/api/device-types/ha-lock.html#_CPPv46HALock">HALock (C++ class)</a>
</li>
Expand Down
Binary file modified docs/objects.inv
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/searchindex.js

Large diffs are not rendered by default.

29 changes: 27 additions & 2 deletions examples/light/light.ino
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,21 @@ HAMqtt mqtt(client, device);

// HALight::BrightnessFeature enables support for setting brightness of the light.
// HALight::ColorTemperatureFeature enables support for setting color temperature of the light.
// Both features are optional and you can remove them if they're not needed.
// HALight::EffectsFeature enables support for setting effect of the light.
// All features are optional, and you can remove them if they're not needed.
// "prettyLight" is unique ID of the light. You should define your own ID.
HALight light("prettyLight", HALight::BrightnessFeature | HALight::ColorTemperatureFeature | HALight::RGBFeature);
HALight light("prettyLight", HALight::BrightnessFeature |
HALight::ColorTemperatureFeature |
HALight::RGBFeature |
HALight::EffectsFeature);

const char* const lightEffects[] = {
"Fire",
"Rainbow",
"Polar light",
"Rain",
"Smoke"
};

void onStateCommand(bool state, HALight* sender) {
Serial.print("State: ");
Expand Down Expand Up @@ -47,6 +59,15 @@ void onRGBColorCommand(HALight::RGBColor color, HALight* sender) {
sender->setRGBColor(color); // report color back to the Home Assistant
}

void onEffectCommand(uint8_t index, HALight* sender) {
Serial.print("Effect index: ");
Serial.println(index);
Serial.print("Effect name: ");
Serial.println(lightEffects[index]);

sender->setEffect(index); // report effect back to the Home Assistant
}

void setup() {
Serial.begin(9600);

Expand Down Expand Up @@ -74,11 +95,15 @@ void setup() {
// light.setMinMireds(50);
// light.setMaxMireds(200);

// Light effects (mandatory if HALight::EffectsFeature is set, optional otherwise)
light.setEffects(lightEffects, 5);

// handle light states
light.onStateCommand(onStateCommand);
light.onBrightnessCommand(onBrightnessCommand); // optional
light.onColorTemperatureCommand(onColorTemperatureCommand); // optional
light.onRGBColorCommand(onRGBColorCommand); // optional
light.onEffectCommand(onEffectCommand); // optional

mqtt.begin(BROKER_ADDR);
}
Expand Down
114 changes: 111 additions & 3 deletions src/device-types/HALight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,31 @@ HALight::HALight(const char* uniqueId, const uint8_t features) :
_maxMireds(),
_currentColorTemperature(0),
_currentRGBColor(),
_effects(nullptr),
_currentEffect(0),
_stateCallback(nullptr),
_brightnessCallback(nullptr),
_colorTemperatureCallback(nullptr),
_rgbColorCallback(nullptr)
_rgbColorCallback(nullptr),
_effectCallback(nullptr)
{

}

HALight::~HALight()
{
if (_effects) {
const uint8_t effectsNb = _effects->getItemsNb();
const HASerializerArray::ItemType* effects = _effects->getItems();

for (uint8_t i = 0; i < effectsNb; i++) {
delete[] effects[i];
}

delete _effects;
}
}

bool HALight::setState(const bool state, const bool force)
{
if (!force && state == _currentState) {
Expand Down Expand Up @@ -122,13 +139,49 @@ bool HALight::setRGBColor(const RGBColor& color, const bool force)
return false;
}

void HALight::setEffects(const char* const effects[], const uint8_t size)
{
if (!(_features & EffectsFeature) || !effects || size == 0 || _effects) { // effects can be set only once
return;
}

_effects = new HASerializerArray(size, false);

uint8_t effectLen = 0;
for (uint8_t i = 0; i < size; i++) {
effectLen = strlen(effects[i]);

char* const effect = new char[effectLen + 1]; // include null terminator
effect[effectLen] = '\0';
memcpy(effect, effects[i], effectLen);

_effects->add(effect);
}
}

bool HALight::setEffect(const uint8_t effect, const bool force)
{
if (!force && effect == _currentEffect) {
return true;
}

if (publishEffect(effect)) {
_currentEffect = effect;
return true;
}

return false;
}

void HALight::buildSerializer()
{
if (_serializer || !uniqueId()) {
// EffectsFeature enabled and no _effects set => unlogical
const bool effectsEnabledButNotSet = (_features & EffectsFeature) && !_effects;
if (_serializer || !uniqueId() || effectsEnabledButNotSet) {
return;
}

_serializer = new HASerializer(this, 19); // 19 - max properties nb
_serializer = new HASerializer(this, 22); // 22 - max properties nb
_serializer->set(AHATOFSTR(HANameProperty), _name);
_serializer->set(AHATOFSTR(HAObjectIdProperty), _objectId);
_serializer->set(HASerializer::WithUniqueId);
Expand Down Expand Up @@ -189,6 +242,17 @@ void HALight::buildSerializer()
_serializer->topic(AHATOFSTR(HARGBStateTopic));
}

if (_features & EffectsFeature) {
_serializer->topic(AHATOFSTR(HAEffectStateTopic));
_serializer->topic(AHATOFSTR(HAEffectCommandTopic));

_serializer->set(
AHATOFSTR(HAEffectsProperty),
_effects,
HASerializer::ArrayPropertyType
);
}

_serializer->set(HASerializer::WithDevice);
_serializer->set(HASerializer::WithAvailability);
_serializer->topic(AHATOFSTR(HAStateTopic));
Expand All @@ -209,6 +273,7 @@ void HALight::onMqttConnected()
publishBrightness(_currentBrightness);
publishColorTemperature(_currentColorTemperature);
publishRGBColor(_currentRGBColor);
publishEffect(_currentEffect);
}

subscribeTopic(uniqueId(), AHATOFSTR(HACommandTopic));
Expand All @@ -224,6 +289,10 @@ void HALight::onMqttConnected()
if (_features & RGBFeature) {
subscribeTopic(uniqueId(), AHATOFSTR(HARGBCommandTopic));
}

if (_features & EffectsFeature) {
subscribeTopic(uniqueId(), AHATOFSTR(HAEffectCommandTopic));
}
}

void HALight::onMqttMessage(
Expand Down Expand Up @@ -258,6 +327,14 @@ void HALight::onMqttMessage(
)
) {
handleRGBCommand(payload, length);
} else if (
HASerializer::compareDataTopics(
topic,
uniqueId(),
AHATOFSTR(HAEffectCommandTopic)
)
) {
handleEffectCommand(payload, length);
}
}

Expand Down Expand Up @@ -317,6 +394,20 @@ bool HALight::publishRGBColor(const RGBColor& color)
return publishOnDataTopic(AHATOFSTR(HARGBStateTopic), str, true);
}

bool HALight::publishEffect(const uint8_t effect)
{
if (!(_features & EffectsFeature) || !_effects || effect >= _effects->getItemsNb()) {
return false;
}

const char* effectName = _effects->getItems()[effect];
if (!effectName) {
return false;
}

return publishOnDataTopic(AHATOFSTR(HAEffectStateTopic), effectName, true);
}

void HALight::handleStateCommand(const uint8_t* cmd, const uint16_t length)
{
(void)cmd;
Expand Down Expand Up @@ -370,4 +461,21 @@ void HALight::handleRGBCommand(const uint8_t* cmd, const uint16_t length)
}
}

void HALight::handleEffectCommand(const uint8_t* cmd, const uint16_t length)
{
if (!_effectCallback) {
return;
}

const uint8_t effectsNb = _effects->getItemsNb();
const HASerializerArray::ItemType* effects = _effects->getItems();

for (uint8_t i = 0; i < effectsNb; i++) {
if (strlen(effects[i]) == length && memcmp(cmd, effects[i], length) == 0) {
_effectCallback(i, this);
return;
}
}
}

#endif
Loading