|
|
- /*
-
- LIGHT (EXPERIMENTAL) IR
-
- Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
- Copyright (C) 2017 by François Déchery
-
- ------------------------------------------------------------------------------------------
- Features :
- - ONLY RGB strips are supported (No RGBW or RGBWW)
- - IR remote supported (but not mandatory)
- - HSV (intuitive) WEB controls
- - MQTT & API "color_rgb" + "color_hsv" + "brightness" parameters
- - Uses the (amazing) Fastled library for fast and natural Color & Brightness
- - Several Animation Modes and Speed (controlled from Remote + Web + MQTT + API)
- ------------------------------------------------------------------------------------------
- Not currently Implemented :
- - Saving/Restoring Settings
- - HomeAssistant
- ------------------------------------------------------------------------------------------
-
- */
-
-
- #ifdef LIGHT_PROVIDER_EXPERIMENTAL_RGB_ONLY_HSV_IR
-
- #include <IRremoteESP8266.h>
- #include <IRrecv.h>
- #include <FastLED.h>
-
- // #### Defined ##########################################################################
- #define ANIM_SPEED_STEP 20
- #define ANIM1_SPEED 350 // flash ON Variable
- #define ANIM1_PAUSE 200 // flash OFF fixed
- #define ANIM2_SPEED 550 // strobe OFF variable
- #define ANIM2_PAUSE 150 // storbe ON fixed
- #define ANIM3_SPEED 100 // fade speed
- #define ANIM4_SPEED 700 // smooth speed
- #define ANIM5_SPEED 200 // party speed
-
- #define BUTTONS_COUNT 24
- #define LED_DURATION 70 // Status led ON duration
-
- // #### Variables ########################################################################
- unsigned long r_but_codes[]={ // IR remote buttons codes
- IR_BUTTON_0 , // Brightness +
- IR_BUTTON_1 , // Brightness -
- IR_BUTTON_2 , // OFF
- IR_BUTTON_3 , // ON
- IR_BUTTON_4 , // Red
- IR_BUTTON_5 , // Green
- IR_BUTTON_6 , // Blue
- IR_BUTTON_7 , // White
- IR_BUTTON_8 , // R1
- IR_BUTTON_9 , // G1
- IR_BUTTON_10 , // B1
- IR_BUTTON_11 , // Flash
- IR_BUTTON_12 , // R2
- IR_BUTTON_13 , // G2
- IR_BUTTON_14 , // B2
- IR_BUTTON_15 , // Strobe
- IR_BUTTON_16 , // R3
- IR_BUTTON_17 , // G3
- IR_BUTTON_18 , // B3
- IR_BUTTON_19 , // Fade
- IR_BUTTON_20 , // R4
- IR_BUTTON_21 , // G4
- IR_BUTTON_22 , // B4
- IR_BUTTON_23 // Smooth
- };
-
- unsigned long r_but_colors[]={ // IR remote buttons colors
- 0, // Brightness +
- 0, // Brightness -
- 0, // OFF
- 0, // ON
- 0xFF0000, // Red
- 0x00FF00, // Green
- 0x0000FF, // Blue
- 0xFFFFFF, // White
- 0xD13A01, // R1
- 0x00E644, // G1
- 0x0040A7, // B1
- 0, // Flash
- 0xE96F2A, // R2
- 0x00BEBF, // G2
- 0x56406F, // B2
- 0, // Strobe
- 0xEE9819, // R3
- 0x00799A, // G3
- 0x944E80, // B3
- 0, // Fade
- 0xFFFF00, // R4
- 0x0060A1, // G4
- 0xEF45AD, // B4
- 0 // Smooth
- };
-
- // variables declarations ###############################################################
- CHSV _cur_color = CHSV(0,255,255);
- CHSV _cur_anim_color = CHSV(0,0,0);
- byte _cur_status = 0 ;
- byte _cur_anim_mode = 0 ;
- byte _cur_anim_step = 0;
- boolean _cur_anim_dir = true;
- unsigned long _cur_anim_speed = 1000;
- unsigned long _anim_last_update = millis();
- unsigned long _last_ir_button = 0;
- unsigned long _last_status_led_time = 0;
-
- IRrecv _ir_recv(LIGHT_IR_PIN); //IRrecv _ir_recv(IR_PIN, IR_LED_PIN); dont work. Why ?
- decode_results _ir_results;
-
-
- // #######################################################################################
- // #### PRIVATE ##########################################################################
- // #######################################################################################
-
- // ---------------------------------------------------------------------------------------
- void _updateStatusLed(){
- if(millis() > _last_status_led_time + LED_DURATION ){
- digitalWrite(LED1_PIN, LOW);
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _flashStatusLed(){
- digitalWrite(LED1_PIN, HIGH);
- _last_status_led_time=millis();
- }
-
- // ---------------------------------------------------------------------------------------
- void _loopProcessIR() {
- if (_ir_recv.decode(&_ir_results)) {
- //dumpIR(&_ir_results);
- //DEBUG_MSG_P(PSTR(".\n"));
- unsigned long code = _ir_results.value;
- DEBUG_MSG_P(PSTR("[IR] received : 0x%X "), code );
- if( code == 0xFFFFFFFF){
- code = _last_ir_button;
- DEBUG_MSG_P(PSTR("(Repeat : %X) "), code );
- }
- DEBUG_MSG_P(PSTR("=> ") );
- _processIrButtons(code);
- _ir_recv.resume(); // Receive the next value
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _processIrButtons(unsigned long code) {
- //DEBUG_MSG_P(PSTR("IR code : %X\n"), code );
- boolean done=false;
- for (int i = 0; i < BUTTONS_COUNT ; i = i + 1) {
- if( code == r_but_codes[i] ){
- //DEBUG_MSG_P(PSTR(" : %X -> "), r_but_colors[i] );
-
- _last_ir_button = 0; //no repat else if specified
-
- if(i == 0){
- _buttonBrightness(true);
- _last_ir_button = code;
- delay(150); //debounce
- }
- else if(i == 1){
- _buttonBrightness(false);
- _last_ir_button = code;
- delay(150); //debounce
- }
- else if(i == 2){
- _buttonPower(false);
- }
- else if(i == 3){
- _buttonPower(true);
- }
- else if(i == 11){
- _buttonAnimMode(1);
- }
- else if(i == 15){
- _buttonAnimMode(2);
- }
- else if(i == 19){
- _buttonAnimMode(3);
- }
- else if(i == 23){
- _buttonAnimMode(4);
- }
- else{
- _buttonColorRVB(r_but_colors[i],0);
- }
- done=true;
- lightUpdate(true, true);
- }
- }
- if(!done){
- _last_ir_button = 0;
- //DEBUG_PRINTHEX(code);
- DEBUG_MSG_P(PSTR("ignored!\n"));
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _buttonPower(boolean on){
- _flashStatusLed();
- DEBUG_MSG_P(PSTR("BUT Power: "));
- _cur_anim_mode=0;
- if(on){
- _cur_status=1;
- DEBUG_MSG_P(PSTR("ON : "));
- _setLedsHSV(_cur_color);
- }
- else{
- _cur_status=0;
- DEBUG_MSG_P(PSTR("OFF : "));
- _setLedsHSV(CHSV {0,0,0});
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _buttonAnimMode(byte val){
- _flashStatusLed();
- DEBUG_MSG_P(PSTR("BUT Anim Mode: %d\n"),val);
- _processAnimation(val, true, true);
- }
-
- // ---------------------------------------------------------------------------------------
- void _setAnimMode(byte val){
- DEBUG_MSG_P(PSTR("[LIGHT] Set AnimMode: %d\n"),val);
- _processAnimation(val, true, false);
- }
-
- // ---------------------------------------------------------------------------------------
- void _buttonBrightness(boolean up){
- DEBUG_MSG_P(PSTR("BUT Brightness: "));
- if(up){
- if(_cur_anim_mode==0){
- DEBUG_MSG_P(PSTR("UP : "));
- _buttonColorHSV(_cur_color, 1 );
- }
- else{
- DEBUG_MSG_P(PSTR("FASTER\n"));
- _buttonChangeSpeed( - ANIM_SPEED_STEP );
- }
- }
- else{
- if(_cur_anim_mode==0){
- DEBUG_MSG_P(PSTR("DOWN : "));
- _buttonColorHSV(_cur_color, -1 );
- }
- else{
- DEBUG_MSG_P(PSTR("SLOWER\n"));
- _buttonChangeSpeed( ANIM_SPEED_STEP );
- }
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _buttonColorHSV(CHSV color, int offset){
- _flashStatusLed();
- DEBUG_MSG_P(PSTR("[LIGHT] Set Color to : "));
- //DEBUG_MSG_P(PSTR("(from HSV=%d,%d,%d) "), color.h, color.s, color.v);
- color=_dimHSV(color,offset);
- //DEBUG_MSG_P(PSTR("(to HSV=%d,%d,%d) "), color.h, color.s, color.v);
- _setLedsHSV(color);
- if(color.v ==0 ){
- _cur_status=0;
- }
- else{
- _cur_status=1;
- }
- _cur_color=color;
- _romSaveCurrentColor();
- }
-
- // ---------------------------------------------------------------------------------------
- void _buttonColorRVB(CRGB color, int offset){
- _buttonColorHSV(_rgbToHsv(color), offset);
- }
-
- // ---------------------------------------------------------------------------------------
- void _buttonChangeSpeed(int offset){
- _flashStatusLed();
- if(offset !=0){
- _cur_anim_speed=_cur_anim_speed + offset ;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- CHSV _dimHSV(CHSV color, int offset){
- offset=offset*10;
- int bright=color.v + offset;
- if(offset ==0){
- return color;
- }
- else if(bright < 1){
- bright=1; // no off
- }
- else if(bright > 255){
- bright=255;
- }
- color.v=bright;
- return color;
- }
-
- // ---------------------------------------------------------------------------------------
- void _setBrightnessMapped(byte val){
- DEBUG_MSG_P(PSTR("[LIGHT] Set from 0-100 Brightness : %u => "), val);
- val =map(val,0,100,0,255);
- _setBrightness(val);
- }
-
- // ---------------------------------------------------------------------------------------
- void _setBrightness(byte val){
- DEBUG_MSG_P(PSTR("[LIGHT] Set Brightness to : %u\n"), val);
- _cur_color.v = val;
- _cur_anim_color.v = val;
- if(val==0){
- _cur_status=0;
- }
- _buttonColorHSV(_cur_color,0);
- }
-
- // ---------------------------------------------------------------------------------------
- void _setAnimSpeed(unsigned long speed){
- if(speed !=0){
- _cur_anim_speed=speed ;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _setLedsRGB(CRGB rgb){
- analogWrite(LIGHT_CH1_PIN, rgb.r);
- analogWrite(LIGHT_CH2_PIN, rgb.g);
- analogWrite(LIGHT_CH3_PIN, rgb.b);
- if(_cur_anim_mode == 0){
- DEBUG_MSG_P(PSTR("RGB=%3u,%3u,%3u\n"), rgb.r, rgb.g, rgb.b);
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _setLedsHSV(CHSV hsv){
- if(_cur_anim_mode == 0){
- DEBUG_MSG_P(PSTR("HSV=%3u,%3u,%3u - "), hsv.h, hsv.s, hsv.v);
- }
- _setLedsRGB( CHSV(hsv) );
- }
-
- // ---------------------------------------------------------------------------------------
- void _confirmFlash(){
- _setLedsRGB(CRGB::Black);
- delay(70);
-
- _setLedsRGB(CRGB::White);
- delay(70);
-
- _setLedsRGB(CRGB::Black);
- delay(70);
-
- _setLedsRGB(CRGB::White);
- delay(70);
-
- _setLedsRGB(CRGB::Black);
- delay(70);
- }
-
- // ---------------------------------------------------------------------------------------
- void _processAnimation(byte mode, boolean init, boolean is_button){
- if(init){
- if(_cur_anim_mode == mode && is_button){
- _confirmFlash();
- DEBUG_MSG_P(PSTR("[ANIM_%d] Stopped !!!\n"), mode);
- _cur_anim_mode=0;
- _cur_status=0;
- return;
- }
- else if(mode == 0){
- DEBUG_MSG_P(PSTR("[ANIM_%d] Stopped !!!\n"), mode);
- _cur_anim_mode=0;
- _cur_status=0;
- return;
- }
- else{
- if(is_button){
- _confirmFlash();
- }
- DEBUG_MSG_P(PSTR("[ANIM_%d] Started !!!\n"), mode);
- }
- }
-
- if(mode==1){
- _anim1(init);
- }
- else if(mode==2){
- _anim2(init);
- }
- else if(mode==3){
- _anim3(init);
- }
- else if(mode==4){
- _anim4(init);
- }
- else if(mode==5){
- _anim5(init);
- }
- else{
- //invalid mode
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // anim1 : flash
- void _anim1(boolean init){
- if(init){
- _cur_anim_mode = 1;
- _cur_anim_speed = ANIM1_SPEED;
- _cur_status = 1;
- _cur_anim_step = 1;
- }
- unsigned long now= millis();
- if(_cur_anim_step==1 && now > (_anim_last_update + _cur_anim_speed) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _setLedsHSV(_cur_color);
- _cur_anim_step=0;
- _anim_last_update = now;
- }
- else if(_cur_anim_step==0 && now > (_anim_last_update + ANIM1_PAUSE) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _setLedsHSV(CHSV {0,0,0});
- _cur_anim_step=1;
- _anim_last_update = now;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // anim2 : strobe
- void _anim2(boolean init){
- if(init){
- _cur_anim_mode = 2;
- _cur_anim_speed = ANIM2_SPEED;
- _cur_status = 1;
- _cur_anim_step = 1;
- }
- unsigned long now= millis();
- if(_cur_anim_step==1 && now > (_anim_last_update + ANIM2_PAUSE) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _setLedsHSV(_cur_color);
- _cur_anim_step=0;
- _anim_last_update = now;
- }
- else if(_cur_anim_step==0 && now > (_anim_last_update + _cur_anim_speed) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _setLedsHSV(CHSV {0,0,0});
- _cur_anim_step=1;
- _anim_last_update = now;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // anim3 : fade
- void _anim3(boolean init){
- if(init){
- _cur_anim_mode = 3;
- _cur_anim_speed = ANIM3_SPEED;
- _cur_status = 1;
- _cur_anim_step = _cur_color.v;
- }
-
- unsigned long now= millis();
- if( now > (_anim_last_update + _cur_anim_speed) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _setLedsHSV( CHSV(_cur_color.h, _cur_color.s, dim8_lin(_cur_anim_step)) );
- if(_cur_anim_dir){
- if(_cur_anim_step == 255){
- _cur_anim_dir=false;
- }
- else{
- _cur_anim_step++;
- }
- }
- else{
- if(_cur_anim_step == 1){
- _cur_anim_dir=true;
- }
- else{
- _cur_anim_step--;
- }
- }
- _anim_last_update = now;
- }
-
- }
-
- // ---------------------------------------------------------------------------------------
- // anim4 : smooth
- void _anim4(boolean init){
- if(init){
- _cur_anim_mode = 4;
- _cur_anim_speed = ANIM4_SPEED;
- _cur_status = 1;
- _cur_anim_step = 0;
- _cur_anim_color = _cur_color;
- _cur_anim_color.v = 255;
- }
-
- unsigned long now= millis();
- if( now > (_anim_last_update + _cur_anim_speed) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _cur_anim_color.h=_cur_anim_step;
- _cur_anim_color.s=255;
- _setLedsHSV( CHSV(_cur_anim_step,255,255) );
- _cur_anim_step++;
- _anim_last_update = now;
- if(_cur_anim_step > 255){
- _cur_anim_step=0;
- }
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // anim5 : party
- void _anim5(boolean init){
- if(init){
- _cur_anim_mode = 5;
- _cur_anim_speed = ANIM5_SPEED;
- _cur_status = 1;
- _cur_anim_step = 0;
- _cur_anim_color = _cur_color;
- _cur_anim_color.s= 255;
- _cur_anim_color.v= 255;
- }
- unsigned long now= millis();
- if(_cur_anim_step == 1 && now > (_anim_last_update + _cur_anim_speed) ){
- DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _cur_anim_color.h = random(0,255);
- _setLedsHSV(_cur_anim_color);
- _cur_anim_step = 0;
- _anim_last_update = now;
- }
- else if(_cur_anim_step==0 && now > (_anim_last_update + _cur_anim_speed + 15) ){
- //DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode);
- _setLedsHSV(CHSV {0,0,0});
- _cur_anim_step = 1;
- _anim_last_update = now;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- void _loopUpdateAnimation(){
- _processAnimation(_cur_anim_mode, false, false);
- }
-
- // ---------------------------------------------------------------------------------------
- CHSV _rgbToHsv(CRGB rgb){
- /*
- if(rgb.r <=1 && rgb.g <=1 && rgb.b <=1){
- DEBUG_MSG_P(PSTR(" {Rounding RGB to black} "));
- return CHSV {0,0,0};
- }
- */
- return rgb2hsv_approximate(rgb);
- }
-
- // ---------------------------------------------------------------------------------------
- void _romSaveCurrentColor(){
- //save it to 1,2,3 positions
- //but dont stress eeprom if not needed
- /*
- CHSV rom =_romLoadColor();
- if(_cur_color.h != rom.h){gw.saveState(1,_cur_color.h);}
- if(_cur_color.s != rom.s){gw.saveState(2,_cur_color.s);}
- if(_cur_color.v != rom.v){gw.saveState(3,_cur_color.v);}
- */
- }
-
- // ---------------------------------------------------------------------------------------
- CHSV _romLoadColor(){
- //load from 1,2,3 positions
- CHSV color;
- /*
- color.h=gw.loadState(1);
- color.s=gw.loadState(2);
- color.v=gw.loadState(3);
- */
- return color;
- }
-
- // ----------------------------------------------
- CRGB _longToRgb(unsigned long rgb){
- CRGB out;
- out.r = rgb >> 16;
- out.g = rgb >> 8 & 0xFF;
- out.b = rgb & 0xFF;
- return out;
- }
-
- // ---------------------------------------------------------------------------------------
- CHSV _longToHsv(unsigned long hsv){
- CHSV out;
- out.h = hsv >> 16;
- out.s = hsv >> 8 & 0xFF;
- out.v = hsv & 0xFF;
- return out;
- }
-
- // ---------------------------------------------------------------------------------------
- unsigned long _rgbToLong(CRGB in){
- return (((long)in.r & 0xFF) << 16) + (((long)in.g & 0xFF) << 8) + ((long)in.b & 0xFF);
- }
-
- // ---------------------------------------------------------------------------------------
- unsigned long _hsvToLong(CHSV in){
- return (((long)in.h & 0xFF) << 16) + (((long)in.s & 0xFF) << 8) + ((long)in.v & 0xFF);
- }
-
- // ---------------------------------------------------------------------------------------
- CRGB _charToRgb(const char * rgb) {
-
- char * p = (char *) rgb;
-
- // if color begins with a # then assume HEX RGB
- if (p[0] == '#') {
- ++p;
- }
- return _longToRgb( strtoul(p, NULL, 16) );
- }
-
- // ---------------------------------------------------------------------------------------
- CHSV _charToHsv(const char * rgb) {
-
- char * p = (char *) rgb;
-
- // if color begins with a # then assume HEX RGB
- if (p[0] == '#') {
- ++p;
- }
- return _longToHsv( strtoul(p, NULL, 16) );
- }
-
-
- // ---------------------------------------------------------------------------------------
- boolean _charColorIsValid(const char * rgb){
- char * p = (char *) rgb;
- if (strlen(p) == 6 || strlen(p) == 7 ){
- return true;
- }
- return false;
- }
-
- // ---------------------------------------------------------------------------------------
- void _CurrentColorToRGB(char * buffer) {
- snprintf_P(buffer, 8, PSTR("%06X"), _rgbToLong( CHSV(_cur_color)));
- }
-
- // ---------------------------------------------------------------------------------------
- void _CurrentColorToHSV(char * buffer) {
- snprintf_P(buffer, 8, PSTR("%06X"), _hsvToLong( _cur_color));
- }
-
- // ---------------------------------------------------------------------------------------
- void _lightColorRestore() {
- /*
- for (unsigned int i=0; i < _channels.size(); i++) {
- _channels[i].value = getSetting("ch", i, 0).toInt();
- }
- _brightness = getSetting("brightness", LIGHT_MAX_BRIGHTNESS).toInt();
- lightUpdate(false, false);
- */
- }
-
-
- // ---------------------------------------------------------------------------------------
- void _lightAPISetup() {
-
- #if WEB_SUPPORT
-
- // API entry points (protected with apikey)
- if (lightHasColor()) {
-
- apiRegister(MQTT_TOPIC_COLOR_RGB, MQTT_TOPIC_COLOR_RGB,
- [](char * buffer, size_t len) {
- _CurrentColorToRGB(buffer);
- },
- [](const char * payload) {
- _SetLightColorRGB(payload);
- lightUpdate(true, true);
- }
- );
-
- apiRegister(MQTT_TOPIC_COLOR_HSV, MQTT_TOPIC_COLOR_HSV,
- [](char * buffer, size_t len) {
- _CurrentColorToHSV(buffer);
- },
- [](const char * payload) {
- _SetLightColorHSV(payload);
- lightUpdate(true, true);
- }
- );
-
- apiRegister(MQTT_TOPIC_BRIGHTNESS, MQTT_TOPIC_BRIGHTNESS,
- [](char * buffer, size_t len) {
- snprintf_P(buffer, len, PSTR("%d"), _cur_color.v);
- },
- [](const char * payload) {
- _setBrightness(atoi(payload));
- lightUpdate(true, true);
- }
- );
-
- apiRegister(MQTT_TOPIC_ANIM_MODE, MQTT_TOPIC_ANIM_MODE,
- [](char * buffer, size_t len) {
- snprintf_P(buffer, len, PSTR("%d"), _cur_anim_mode);
- },
- [](const char * payload) {
- _setAnimMode(atoi(payload));
- lightUpdate(true, true);
- }
- );
-
- apiRegister(MQTT_TOPIC_ANIM_SPEED, MQTT_TOPIC_ANIM_SPEED,
- [](char * buffer, size_t len) {
- snprintf_P(buffer, len, PSTR("%d"), _cur_anim_speed);
- },
- [](const char * payload) {
- _setAnimSpeed(atoi(payload));
- lightUpdate(true, true);
- }
- );
-
-
- }
- /*
- for (unsigned int id=0; id<lightChannels(); id++) {
-
- char url[15];
- snprintf_P(url, sizeof(url), PSTR("%s/%d"), MQTT_TOPIC_CHANNEL, id);
-
- char key[10];
- snprintf_P(key, sizeof(key), PSTR("%s%d"), MQTT_TOPIC_CHANNEL, id);
-
- apiRegister(url, key,
- [id](char * buffer, size_t len) {
- snprintf_P(buffer, len, PSTR("%d"), lightChannel(id));
- },
- [id](const char * payload) {
- lightChannel(id, atoi(payload));
- lightUpdate(true, true);
- }
- );
-
- }
- */
- #endif // WEB_SUPPORT
-
- }
-
-
- /*
- // #######################################################################################
-
- // ---------------------------------------------------------------------------------------
- CRGB _hsvToRgb(CHSV hsv){
- if(hsv.v <=1){
- DEBUG_MSG_P(PSTR(" {Rounding HSV to black}\n"));
- hsv.v=0;
- }
- CRGB rgb=CHSV(hsv);
- //round to black
- if(rgb.r <=1 && rgb.g <=1 && rgb.b <=1){
- DEBUG_MSG_P(PSTR(" {Rounding RGB to black}\n"));
- rgb=CRGB::Black;
- }
- return rgb;
- }
-
-
- // ---------------------------------------------------------------------------------------
- void _strToUpper(char * str){
- for(int i=0; i<6; i++){
- //a-z
- if (97<=str[i]&&str[i]<=122){
- str[i]-=32;
- }
- }
- }
-
- */
-
-
-
- // #######################################################################################
- // #### PUBLIC ###########################################################################
- // #######################################################################################
-
-
- // ################################################################
- void lightSetup() {
-
- DEBUG_MSG_P(PSTR("[LIGHT] LIGHT_PROVIDER = %d (With IR)\n"), LIGHT_PROVIDER);
-
- pinMode(LIGHT_CH1_PIN, OUTPUT);
- pinMode(LIGHT_CH2_PIN, OUTPUT);
- pinMode(LIGHT_CH3_PIN, OUTPUT);
-
- _ir_recv.enableIRIn(); // Start the receiver
-
- //confirmRgb();
-
- _cur_color = _romLoadColor();
-
- _lightColorRestore();
- _lightAPISetup();
- mqttRegister(_lightMQTTCallback);
-
-
- }
-
- // ---------------------------------------------------------------------------------------
- void lightLoop() {
- _loopProcessIR();
- _loopUpdateAnimation();
- _updateStatusLed();
- }
-
- // ---------------------------------------------------------------------------------------
- void lightUpdate(bool save, bool forward) {
- //DEBUG_MSG_P(PSTR("[LIGHT] Updating... \n"));
-
- // _lightProviderUpdate();
-
- // Report color & brightness to MQTT broker
- if (forward) lightMQTT();
-
- // Report color to WS clients (using current brightness setting)
- #if WEB_SUPPORT
- {
- DynamicJsonBuffer jsonBuffer;
- JsonObject& root = jsonBuffer.createObject();
- root["colorVisible"] = 1;
- root["useColor"] = getSetting("useColor", LIGHT_USE_COLOR).toInt() == 1;
- root["useWhite"] = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
- root["useGamma"] = getSetting("useGamma", LIGHT_USE_GAMMA).toInt() == 1;
-
- root["anim_mode"] = lightAnimMode();
- root["anim_speed"] = lightAnimSpeed();
- JsonObject& color_hsv = root.createNestedObject("color_hsv");
- color_hsv["h"] = lightColorH();
- color_hsv["s"] = lightColorS();
- color_hsv["v"] = lightColorV();
-
- //root["color_hsv"] = lightColor();
- //root["brightness"] = _cur_color.v;
-
- // RGB channels
- //JsonArray& channels = root.createNestedArray("channels");
- //for (unsigned char id=0; id < lightChannels(); id++) {
- // channels.add(lightChannel(id));
- //}
-
- // Relay
- JsonArray& relay = root.createNestedArray("relayStatus");
- relay.add(_cur_status);
-
- String output;
- root.printTo(output);
- wsSend(output.c_str());
- //DEBUG_MSG_P(PSTR("JSON : %s"), output.c_str() );
- }
- #endif
-
- // Delay saving to EEPROM 5 seconds to avoid wearing it out unnecessarily
- //if (save) colorTicker.once(LIGHT_SAVE_DELAY, _lightColorSave);
- }
-
-
- // ---------------------------------------------------------------------------------------
- void lightMQTT() {
-
- char buffer[8];
-
- if (lightHasColor()) {
-
- // RGB Color
- _CurrentColorToRGB(buffer);
- mqttSend(MQTT_TOPIC_COLOR_RGB, buffer);
-
- // HSV Color
- _CurrentColorToHSV(buffer);
- mqttSend(MQTT_TOPIC_COLOR_HSV, buffer);
-
- // Brightness
- snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _cur_color.v);
- mqttSend(MQTT_TOPIC_BRIGHTNESS, buffer);
-
- // Anim Mode
- snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _cur_anim_mode);
- mqttSend(MQTT_TOPIC_ANIM_MODE, buffer);
-
- // Anim Speed
- snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _cur_anim_speed);
- mqttSend(MQTT_TOPIC_ANIM_SPEED, buffer);
- }
-
- // Channels
- //for (unsigned int i=0; i < _channels.size(); i++) {
- // snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _channels[i].value);
- // mqttSend(MQTT_TOPIC_CHANNEL, i, buffer);
- //}
- }
-
- // ---------------------------------------------------------------------------------------
- // Get Number of Channels
- unsigned char lightChannels() {
- return 3;
- }
-
- // ---------------------------------------------------------------------------------------
- // Get Channel's Value
- unsigned int lightChannel(unsigned char id) {
-
- CRGB current_rvb = CHSV(_cur_color);
- if(id == 0 ){
- return current_rvb.r;
- }
- else if(id == 1 ){
- return current_rvb.g;
- }
- else if(id == 2 ){
- return current_rvb.b;
- }
- else{
- DEBUG_MSG_P(PSTR(" [ERROR] GET lightChannel : %s\n"), id);
- return 0;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // Set Channel's Value
- void lightChannel(unsigned char id, unsigned int value) {
- DEBUG_MSG_P(PSTR("[WEB|API] Set Color Channel "));
- value= constrain(value, 0, 255);
- CRGB current_rvb = CHSV(_cur_color);
-
- if(id == 0 ){
- DEBUG_MSG_P(PSTR("RED to : %d => "), value);
- current_rvb.r=value;
- _buttonColorRVB(current_rvb,0);
- }
- else if(id == 1 ){
- DEBUG_MSG_P(PSTR("GREEN to : %d => "), value);
- current_rvb.g=value;
- _buttonColorRVB(current_rvb,0);
- }
- else if(id == 2 ){
- DEBUG_MSG_P(PSTR("BLUE to : %d => "), value);
- current_rvb.b=value;
- _buttonColorRVB(current_rvb,0);
- }
- else{
- DEBUG_MSG_P(PSTR(" [ERROR] SET lightChannel %s To %d \n"), id, value);
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // Get Brightness
- unsigned int lightBrightness() {
- return _cur_color.v;
- }
-
- // ---------------------------------------------------------------------------------------
- // Set Brightness
- void lightBrightness(unsigned int b) {
- b=constrain(b, 0, 255);
- DEBUG_MSG_P(PSTR("[WEB|API] Set Brightness to : %d\n"), b);
- _cur_color.v=b;
- _setLedsHSV(_cur_color);
-
- //set status
- if(b > 0){
- _cur_status=1;
- }
- else{
- _cur_status=0;
- }
- }
-
- // ---------------------------------------------------------------------------------------
- // Get Color
- String lightColor() {
- char rgb[8];
- snprintf_P(rgb, 8, PSTR("#%06X"), _rgbToLong( CHSV(_cur_color)));
- return String(rgb);
- //return String("");
- }
-
- String lightColorH(){
- return String(_cur_color.h);
- }
- String lightColorS(){
- return String(_cur_color.s);
- }
- String lightColorV(){
- return String(_cur_color.v);
- }
-
-
- // ---------------------------------------------------------------------------------------
- // Set Color
- void lightColor(const char * color) {
- //used only from settings
- _SetLightColorRGB(color);
- }
-
- void _SetLightColorRGB(const char * color) {
- //used only from settings
- DEBUG_MSG_P(PSTR("[WEB|API] Set (#RGB) Color to : "));
- if( _charColorIsValid(color) ){
- DEBUG_MSG_P(PSTR("%s \n"), color);
- _buttonColorRVB(_charToRgb(color), 0);
- }
- else{
- DEBUG_MSG_P(PSTR(" Canceled ('%s' is invalid) !\n"), color);
- }
- }
-
- void _SetLightColorHSV(const char * color) {
- DEBUG_MSG_P(PSTR("[WEB|API] Set (#HSV) Color to : "));
- if( _charColorIsValid(color) ){
- DEBUG_MSG_P(PSTR("%s \n"), color);
- _buttonColorHSV(_charToHsv(color), 0);
- }
- else{
- DEBUG_MSG_P(PSTR(" Canceled ('%s' is invalid) !\n"), color);
- }
- }
-
- void setLightColor (const char * h, const char * s, const char * v){
- DEBUG_MSG_P(PSTR("[WEB|API] Set Color from (%s,%s,%s) "), h, s, v);
- CHSV color;
- color.h=strtoul(h, NULL, 10);
- color.s=strtoul(s, NULL, 10);
- color.v=strtoul(v, NULL, 10);
- DEBUG_MSG_P(PSTR("to (%d,%d,%d) "), color.h, color.s, color.v);
- _buttonColorRVB(color, 0);
- }
-
-
- // ---------------------------------------------------------------------------------------
- bool lightHasColor() {
- // bool useColor = getSetting("useColor", LIGHT_USE_COLOR).toInt() == 1;
- // return useColor && (_channels.size() > 2);
- //if(_cur_status || _cur_anim_mode){return 1;}
- return true;
- }
-
-
- // ---------------------------------------------------------------------------------------
- // Get State
- bool lightState() {
- //DEBUG_MSG_P(PSTR("[->LIGHT] _cur_status is : %d \n"),_cur_status);
- return _cur_status;
- }
-
- // ---------------------------------------------------------------------------------------
- // Set State
- void lightState(bool state){
- DEBUG_MSG_P(PSTR("[WEB|API] Set Relay to : %u => "), state);
- //if(state != _cur_status){
- _buttonPower(state);
- //}
- }
-
-
- // ---------------------------------------------------------------------------------------
- String lightAnimMode(){
- return String(_cur_anim_mode);
- }
- void lightAnimMode(const char * val){
- DEBUG_MSG_P(PSTR("[WEB|API] Set AnimMode to %s\n"), val);
- _setAnimMode(strtoul(val, NULL, 10));
- }
- // ---------------------------------------------------------------------------------------
- String lightAnimSpeed(){
- return String(_cur_anim_speed);
- }
- void lightAnimSpeed(const char * val){
- DEBUG_MSG_P(PSTR("[WEB|API] Set AnimSpeed to %s \n"), val);
- _setAnimSpeed(strtoul(val, NULL, 10));
- }
-
-
- // ---------------------------------------------------------------------------------------
- // MQTT
- // ---------------------------------------------------------------------------------------
-
- void _lightMQTTCallback(unsigned int type, const char * topic, const char * payload) {
-
-
- if (type == MQTT_CONNECT_EVENT) {
-
- if (lightHasColor()) {
- mqttSubscribe(MQTT_TOPIC_BRIGHTNESS);
- mqttSubscribe(MQTT_TOPIC_COLOR_RGB);
- mqttSubscribe(MQTT_TOPIC_COLOR_HSV);
- mqttSubscribe(MQTT_TOPIC_ANIM_MODE);
- mqttSubscribe(MQTT_TOPIC_ANIM_SPEED);
- }
-
- //char buffer[strlen(MQTT_TOPIC_CHANNEL) + 3];
- //snprintf_P(buffer, sizeof(buffer), PSTR("%s/+"), MQTT_TOPIC_CHANNEL);
- //mqttSubscribe(buffer);
-
- }
-
- if (type == MQTT_MESSAGE_EVENT) {
-
- // Match topic
- String t = mqttSubtopic((char *) topic);
-
- // Color RGB
- if (t.equals(MQTT_TOPIC_COLOR_RGB)) {
- _SetLightColorRGB(payload);
- lightUpdate(true, mqttForward());
- }
-
- // Color HSV
- if (t.equals(MQTT_TOPIC_COLOR_HSV)) {
- _SetLightColorHSV(payload);
- lightUpdate(true, mqttForward());
- }
-
- // ANIM Mode
- if (t.equals(MQTT_TOPIC_ANIM_MODE)) {
- _setAnimMode(atoi(payload));
- lightUpdate(true, mqttForward());
- }
-
- // ANIM Speed
- if (t.equals(MQTT_TOPIC_ANIM_SPEED)) {
- _setAnimSpeed(atoi(payload));
- lightUpdate(true, mqttForward());
- }
-
- // Brightness
- if (t.equals(MQTT_TOPIC_BRIGHTNESS)) {
- _setBrightness (constrain(atoi(payload), 0, LIGHT_MAX_BRIGHTNESS));
- lightUpdate(true, mqttForward());
- }
-
- /*
- // Channel
- if (t.startsWith(MQTT_TOPIC_CHANNEL)) {
- unsigned int channelID = t.substring(strlen(MQTT_TOPIC_CHANNEL)+1).toInt();
- if (channelID >= _channels.size()) {
- DEBUG_MSG_P(PSTR("[LIGHT] Wrong channelID (%d)\n"), channelID);
- return;
- }
- lightChannel(channelID, atoi(payload));
- lightUpdate(true, mqttForward());
- }
- */
- }
- }
-
- #endif // LIGHT_IR_PIN
|