2020-03-25 09:00:55 +01:00
|
|
|
#include "wled.h"
|
2020-03-31 02:38:08 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
|
2023-01-06 09:24:29 +01:00
|
|
|
*
|
2020-03-31 02:38:08 +02:00
|
|
|
* This was put together from these two excellent projects:
|
|
|
|
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
|
|
|
|
* https://github.com/probonopd/ESP8266HueEmulator
|
|
|
|
*/
|
|
|
|
#include "src/dependencies/espalexa/EspalexaDevice.h"
|
2018-01-10 00:37:45 +01:00
|
|
|
|
2018-11-01 15:36:13 +01:00
|
|
|
#ifndef WLED_DISABLE_ALEXA
|
2019-03-01 17:10:42 +01:00
|
|
|
void onAlexaChange(EspalexaDevice* dev);
|
2019-01-09 22:52:42 +01:00
|
|
|
|
2017-02-21 23:59:47 +01:00
|
|
|
void alexaInit()
|
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
if (!alexaEnabled || !WLED_CONNECTED) return;
|
|
|
|
|
|
|
|
espalexa.removeAllDevices();
|
|
|
|
// the original configured device for on/off or macros (added first, i.e. index 0)
|
|
|
|
espalexaDevice = new EspalexaDevice(alexaInvocationName, onAlexaChange, EspalexaDeviceType::extendedcolor);
|
|
|
|
espalexa.addDevice(espalexaDevice);
|
|
|
|
|
2023-01-06 09:24:29 +01:00
|
|
|
// up to 9 devices (added second, third, ... i.e. index 1 to 9) serve for switching on up to nine presets (preset IDs 1 to 9 in WLED),
|
2022-10-25 23:42:26 +02:00
|
|
|
// names are identical as the preset names, switching off can be done by switching off any of them
|
|
|
|
if (alexaNumPresets) {
|
|
|
|
String name = "";
|
2023-01-06 09:24:29 +01:00
|
|
|
for (byte presetIndex = 1; presetIndex <= alexaNumPresets; presetIndex++)
|
2019-01-09 22:52:42 +01:00
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
if (!getPresetName(presetIndex, name)) break; // no more presets
|
|
|
|
EspalexaDevice* dev = new EspalexaDevice(name.c_str(), onAlexaChange, EspalexaDeviceType::extendedcolor);
|
|
|
|
espalexa.addDevice(dev);
|
2018-11-09 17:00:36 +01:00
|
|
|
}
|
2017-02-21 23:59:47 +01:00
|
|
|
}
|
2022-10-25 23:42:26 +02:00
|
|
|
espalexa.begin(&server);
|
2017-02-21 23:59:47 +01:00
|
|
|
}
|
|
|
|
|
2019-01-09 22:52:42 +01:00
|
|
|
void handleAlexa()
|
2017-02-21 23:59:47 +01:00
|
|
|
{
|
2019-10-18 13:26:39 +02:00
|
|
|
if (!alexaEnabled || !WLED_CONNECTED) return;
|
2019-01-09 22:52:42 +01:00
|
|
|
espalexa.loop();
|
2017-02-21 23:59:47 +01:00
|
|
|
}
|
|
|
|
|
2019-03-01 17:10:42 +01:00
|
|
|
void onAlexaChange(EspalexaDevice* dev)
|
2017-12-28 00:37:13 +01:00
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
EspalexaDeviceProperty m = dev->getLastChangedProperty();
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2019-03-01 17:10:42 +01:00
|
|
|
if (m == EspalexaDeviceProperty::on)
|
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
if (dev->getId() == 0) // Device 0 is for on/off or macros
|
2019-01-09 22:52:42 +01:00
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
if (!macroAlexaOn)
|
2019-01-09 22:52:42 +01:00
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
if (bri == 0)
|
|
|
|
{
|
|
|
|
bri = briLast;
|
|
|
|
stateUpdated(CALL_MODE_ALEXA);
|
|
|
|
}
|
2023-01-06 09:24:29 +01:00
|
|
|
} else
|
2022-10-25 23:42:26 +02:00
|
|
|
{
|
|
|
|
applyPreset(macroAlexaOn, CALL_MODE_ALEXA);
|
|
|
|
if (bri == 0) dev->setValue(briLast); //stop Alexa from complaining if macroAlexaOn does not actually turn on
|
2019-01-09 22:52:42 +01:00
|
|
|
}
|
2022-10-25 23:42:26 +02:00
|
|
|
} else // switch-on behavior for preset devices
|
|
|
|
{
|
|
|
|
// turn off other preset devices
|
|
|
|
for (byte i = 1; i < espalexa.getDeviceCount(); i++)
|
|
|
|
{
|
|
|
|
if (i == dev->getId()) continue;
|
|
|
|
espalexa.getDevice(i)->setValue(0); // turn off other presets
|
|
|
|
}
|
|
|
|
|
|
|
|
applyPreset(dev->getId(), CALL_MODE_ALEXA); // in alexaInit() preset 1 device was added second (index 1), preset 2 third (index 2) etc.
|
2021-06-14 01:58:12 +02:00
|
|
|
}
|
2019-03-01 17:10:42 +01:00
|
|
|
} else if (m == EspalexaDeviceProperty::off)
|
2018-01-09 11:55:07 +01:00
|
|
|
{
|
2019-01-09 22:52:42 +01:00
|
|
|
if (!macroAlexaOff)
|
|
|
|
{
|
|
|
|
if (bri > 0)
|
|
|
|
{
|
|
|
|
briLast = bri;
|
|
|
|
bri = 0;
|
2022-02-20 22:24:11 +01:00
|
|
|
stateUpdated(CALL_MODE_ALEXA);
|
2019-01-09 22:52:42 +01:00
|
|
|
}
|
2023-01-06 09:24:29 +01:00
|
|
|
} else
|
2022-10-25 23:42:26 +02:00
|
|
|
{
|
2021-07-09 18:54:28 +02:00
|
|
|
applyPreset(macroAlexaOff, CALL_MODE_ALEXA);
|
2022-10-25 23:42:26 +02:00
|
|
|
// below for loop stops Alexa from complaining if macroAlexaOff does not actually turn off
|
|
|
|
}
|
|
|
|
for (byte i = 0; i < espalexa.getDeviceCount(); i++)
|
|
|
|
{
|
|
|
|
espalexa.getDevice(i)->setValue(0);
|
2021-06-14 01:58:12 +02:00
|
|
|
}
|
2019-03-01 17:10:42 +01:00
|
|
|
} else if (m == EspalexaDeviceProperty::bri)
|
2018-01-09 11:55:07 +01:00
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
bri = dev->getValue();
|
2022-02-20 22:24:11 +01:00
|
|
|
stateUpdated(CALL_MODE_ALEXA);
|
2019-01-09 22:52:42 +01:00
|
|
|
} else //color
|
2018-01-09 11:55:07 +01:00
|
|
|
{
|
2022-10-25 23:42:26 +02:00
|
|
|
if (dev->getColorMode() == EspalexaColorMode::ct) //shade of white
|
2020-03-25 00:59:48 +01:00
|
|
|
{
|
2022-02-23 19:20:07 +01:00
|
|
|
byte rgbw[4];
|
2022-10-25 23:42:26 +02:00
|
|
|
uint16_t ct = dev->getCt();
|
2023-05-31 20:12:17 +02:00
|
|
|
if (!ct) return;
|
|
|
|
uint16_t k = 1000000 / ct; //mireds to kelvin
|
|
|
|
|
|
|
|
if (strip.hasCCTBus()) {
|
|
|
|
bool hasManualWhite = strip.getActiveSegsLightCapabilities(true) & SEG_CAPABILITY_W;
|
|
|
|
|
|
|
|
strip.setCCT(k);
|
|
|
|
if (hasManualWhite) {
|
|
|
|
rgbw[0] = 0; rgbw[1] = 0; rgbw[2] = 0; rgbw[3] = 255;
|
|
|
|
} else {
|
|
|
|
rgbw[0] = 255; rgbw[1] = 255; rgbw[2] = 255; rgbw[3] = 0;
|
|
|
|
dev->setValue(255);
|
|
|
|
}
|
|
|
|
} else if (strip.hasWhiteChannel()) {
|
2020-03-25 00:59:48 +01:00
|
|
|
switch (ct) { //these values empirically look good on RGBW
|
2022-02-23 19:20:07 +01:00
|
|
|
case 199: rgbw[0]=255; rgbw[1]=255; rgbw[2]=255; rgbw[3]=255; break;
|
|
|
|
case 234: rgbw[0]=127; rgbw[1]=127; rgbw[2]=127; rgbw[3]=255; break;
|
|
|
|
case 284: rgbw[0]= 0; rgbw[1]= 0; rgbw[2]= 0; rgbw[3]=255; break;
|
|
|
|
case 350: rgbw[0]=130; rgbw[1]= 90; rgbw[2]= 0; rgbw[3]=255; break;
|
|
|
|
case 383: rgbw[0]=255; rgbw[1]=153; rgbw[2]= 0; rgbw[3]=255; break;
|
2023-05-31 20:12:17 +02:00
|
|
|
default : colorKtoRGB(k, rgbw);
|
2020-03-25 00:59:48 +01:00
|
|
|
}
|
|
|
|
} else {
|
2022-02-23 19:20:07 +01:00
|
|
|
colorKtoRGB(k, rgbw);
|
2020-03-25 00:59:48 +01:00
|
|
|
}
|
2022-02-24 13:43:12 +01:00
|
|
|
strip.setColor(0, RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]));
|
2020-03-25 00:59:48 +01:00
|
|
|
} else {
|
2022-10-25 23:42:26 +02:00
|
|
|
uint32_t color = dev->getRGB();
|
2022-02-23 19:20:07 +01:00
|
|
|
strip.setColor(0, color);
|
2020-03-25 00:59:48 +01:00
|
|
|
}
|
2022-02-23 19:20:07 +01:00
|
|
|
stateUpdated(CALL_MODE_ALEXA);
|
2018-01-09 11:55:07 +01:00
|
|
|
}
|
|
|
|
}
|
2018-01-07 22:52:48 +01:00
|
|
|
|
2018-11-09 17:00:36 +01:00
|
|
|
|
2018-11-01 15:36:13 +01:00
|
|
|
#else
|
2018-11-09 17:00:36 +01:00
|
|
|
void alexaInit(){}
|
|
|
|
void handleAlexa(){}
|
2018-11-01 15:36:13 +01:00
|
|
|
#endif
|