#ifdef ENABLE_MOON // Needs refactoring // Use https://adrianotiger.github.io/Neopixel-Effect-Generator/ for inspiration // Read up on final comment at https://forum.arduino.cc/index.php?topic=534060.0 #include /* * Based on https://adrianotiger.github.io/Neopixel-Effect-Generator/ * TODO: Refactor for just a single string effect, less frills * Rainbow pattern */ class Strip { public: uint8_t effect; uint8_t effects; uint16_t effStep; unsigned long effStart; Adafruit_NeoPixel strip; Strip(uint16_t leds, uint8_t pin, uint8_t toteffects) : strip(leds, pin, NEO_GRB + NEO_KHZ800) { effect = -1; effects = toteffects; Reset(); } void Reset(){ effStep = 0; effect = (effect + 1) % effects; effStart = millis(); } }; struct Loop { uint8_t currentChild; uint8_t childs; bool timeBased; uint16_t cycles; uint16_t currentTime; Loop(uint8_t totchilds, bool timebased, uint16_t tottime) {currentTime=0;currentChild=0;childs=totchilds;timeBased=timebased;cycles=tottime;} }; Strip strip_0(7, MOON_PIXEL, 7 ); struct Loop strip0loop0(1, false, 1); //[GLOBAL_VARIABLES] int speed = 200; // started at 101 uint8_t strip0_loop0_eff0() { // Strip ID: 0 - Effect: Rainbow - LEDS: 7 // Steps: 35 - Delay: 100 // Colors: 6 (255.255.0, 0.255.0, 0.0.255, 255.0.255, 255.0.0, 255.255.255, ) // Options: toLeft=true, if(millis() - strip_0.effStart < 100 * (strip_0.effStep)) return 0x00; float factor1, factor2; uint16_t ind; for(uint16_t j=0;j<7;j++) { ind = strip_0.effStep + j * 1; switch((int)((ind % 35) / 5.833333333333333)) { case 0: factor1 = 1.0 - ((float)(ind % 35 - 0 * 5.833333333333333) / 5.833333333333333); factor2 = (float)((int)(ind - 0) % 35) / 5.833333333333333; strip_0.strip.setPixelColor(j, 255 * factor1 + 0 * factor2, 255 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2); break; case 1: factor1 = 1.0 - ((float)(ind % 35 - 1 * 5.833333333333333) / 5.833333333333333); factor2 = (float)((int)(ind - 5.833333333333333) % 35) / 5.833333333333333; strip_0.strip.setPixelColor(j, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2, 0 * factor1 + 255 * factor2); break; case 2: factor1 = 1.0 - ((float)(ind % 35 - 2 * 5.833333333333333) / 5.833333333333333); factor2 = (float)((int)(ind - 11.666666666666666) % 35) / 5.833333333333333; strip_0.strip.setPixelColor(j, 0 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 255 * factor2); break; case 3: factor1 = 1.0 - ((float)(ind % 35 - 3 * 5.833333333333333) / 5.833333333333333); factor2 = (float)((int)(ind - 17.5) % 35) / 5.833333333333333; strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2); break; case 4: factor1 = 1.0 - ((float)(ind % 35 - 4 * 5.833333333333333) / 5.833333333333333); factor2 = (float)((int)(ind - 23.333333333333332) % 35) / 5.833333333333333; strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 0 * factor1 + 255 * factor2, 0 * factor1 + 255 * factor2); break; case 5: factor1 = 1.0 - ((float)(ind % 35 - 5 * 5.833333333333333) / 5.833333333333333); factor2 = (float)((int)(ind - 29.166666666666664) % 35) / 5.833333333333333; strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 255 * factor1 + 255 * factor2, 255 * factor1 + 0 * factor2); break; } } if(strip_0.effStep >= 35) {strip_0.Reset(); return 0x03; } else strip_0.effStep++; return 0x01; } uint8_t strip0_loop0() { uint8_t ret = 0x00; switch(strip0loop0.currentChild) { case 0: ret = strip0_loop0_eff0();break; } if(ret & 0x02) { ret &= 0xfd; if(strip0loop0.currentChild + 1 >= strip0loop0.childs) { strip0loop0.currentChild = 0; if(++strip0loop0.currentTime >= strip0loop0.cycles) {strip0loop0.currentTime = 0; ret |= 0x02;} } else { strip0loop0.currentChild++; } }; return ret; } void strips_loop() { if(strip0_loop0() & 0x01) strip_0.strip.show(); } /* * Interface with other modules */ void newcmd(String cmd) { cmd.toLowerCase(); if(cmd.equals("off")) { settings.mode = 0; PRINTLN_SERIAL("Moon off"); strip_0.strip.setBrightness(0); // 0-255 state.text = "Moon switched off"; } if(cmd.equals("on")) { settings.mode = 1; PRINTLN_SERIAL("Moon switched on"); strip_0.strip.setBrightness(10); // 0-255 state.text = "Moon switched off"; } } void module_message(const String& shorttopic, const String& message) { char msgptr[10]; String buffer; if(shorttopic.equalsIgnoreCase("cmd")) { if(message.equalsIgnoreCase("off")) { state.mode = 0; PRINTLN_SERIAL("Moon off"); strip_0.strip.setBrightness(0); // 0-255 state.text = "Moon switched off"; } else if(message.equalsIgnoreCase("on")) { state.mode = 1; PRINTLN_SERIAL("Moon switched on"); strip_0.strip.setBrightness(10); // 0-255 state.text = "Moon switched off"; } } else if(shorttopic.equalsIgnoreCase("mode")) { if(message.equals("off")) { state.mode = 0; PRINTLN_SERIAL("Shutting off"); } else if(message.startsWith("0x")) { state.mode = 1; message.toCharArray(msgptr, 9); state.color = strtoll( &msgptr[2], NULL, 16); sprintf(printbuffer, "Switching to static color 0x%x", state.color); PRINTLN_SERIAL(printbuffer); } else if(message.startsWith("#")) { state.mode = 1; message.toCharArray(msgptr, 8); state.color = strtoll( &msgptr[1], NULL, 16); sprintf(printbuffer, "Switching to static color 0x%x", state.color); PRINTLN_SERIAL(printbuffer); } else if(message.equals("rainbow")) { state.mode = 2; PRINTLN_SERIAL("Switching to rainbow mode"); } mqtt_publish((deviceprefix + "log"), ("mode=" + String(state.mode))); // @@@FIXME@@@ this needs to go elsewhere } else if(shorttopic.equalsIgnoreCase("brightness")) { PRINTLN_SERIAL("Setting brightness to " + message); settings.brightness = message.toInt(); strip_0.strip.setBrightness(settings.brightness); buffer = "brightness="; buffer.concat(settings.brightness); mqtt_publish((deviceprefix + "log"), buffer.c_str()); // @@@FIXME@@@ this needs to go elsewhere } } /* * Setup and loop code. Be cooperative! No delays, timers. */ void moon_setup() { PRINTLN_SERIAL("initialising module Moon"); strip_0.strip.setBrightness(2); // 0-255 strip_0.strip.begin(); } void moon_loop() { uint16_t r; switch(state.mode) { case 0: // Off for(r=0; r< strip_0.strip.numPixels(); r++) { strip_0.strip.setPixelColor(r, 0,0,0); } strip_0.strip.show(); break; case 1: // Static color for(r=0; r< strip_0.strip.numPixels(); r++) { // Split the set color code up into r, g, b values int rval = state.color >> 16; int gval = state.color >> 8 & 0xFF; int bval = state.color & 0xFF; strip_0.strip.setPixelColor(r, rval, gval, bval); } strip_0.strip.show(); break; case 2: // Rainbow strips_loop(); break; } } #endif