Team Members: Ziai, Iri, Vanessa

1: Final Concept Idea

Untitled

Untitled

Untitled

We employ the principle of the Internet of Things. There are two boxes; box A keeps blinking until someone approaches, at which point the blinking stops. Simultaneously, due to the proximity of a person, box B lights up. The principle involves using MQTTX to receive the signal through box A and relay it to box B, prompting the light, regardless of its location.

2: Experiment

Untitled

3: Code:

Code for Sender:

/*
  ArduinoMqttClient - WiFi Simple Sender

  This example connects to a MQTT broker and publishes a message to
  a topic once a second.

  The circuit:
  - Arduino MKR 1000, MKR 1010 or Uno WiFi Rev2 board

  This example code is in the public domain.
*/

#include <ArduinoMqttClient.h>
#include <Adafruit_NeoPixel.h>

#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
#include <WiFiNINA.h>
#elif defined(ARDUINO_SAMD_MKR1000)
#include <WiFi101.h>
#elif defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_GIGA)
#include <WiFi.h>
#endif
#include <Ultrasonic.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;  // your network SSID (name)
char pass[] = SECRET_PASS;  // your network password (use for WPA, or use as key for WEP)

// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate
//    flashed in the WiFi module.

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "23.21.151.236";
int port = 1883;
const char topic[] = "ultrasonic";
bool isOn = false;

const long interval = 250;
unsigned long previousDistanceMillis = 0;

int count = 0;

const int LED1 = 4;
const int LED2 = 7;

Ultrasonic ultrasonic(3, 2);
int distance;

// #define PIN            12 //sets the pin on which the neopixels are connected
#define NUMPIXELS 55      //defines the number of pixels in the strip
#define interval 5        //defines the delay interval between running the functions
#define wifiRetryTimes 0  //number of times to try the wifi router before going into AP mode (set to 0 if AP only)
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LED1, NEO_GRB + NEO_KHZ800);

uint32_t red = pixels.Color(255, 0, 0);
uint32_t blue = pixels.Color(0, 0, 255);
uint32_t green = pixels.Color(0, 255, 0);
uint32_t pixelColour;
uint32_t lastColor;
float activeColor[] = { 255, 0, 0 };  //sets the default color to red

boolean NeoState[] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, true };  //Active Neopixel Function (off by default)

int neopixMode = 0;            //sets a mode to run each of the functions
long previousMillis = 0;       // a long value to store the millis()
long lastAllCycle = 0;         // last cycle in the ALL() function
long previousColorMillis = 0;  // timer for the last color change
int i = 0;                     //sets the pixel number in newTheatreChase() and newColorWipe()
int CWColor = 0;               //sets the newColorWipe() color value 0=Red, 1=Green, 2=Blue
int j;                         //sets the pixel to skip in newTheatreChase() and newTheatreChaseRainbow()
int cycle = 0;                 //sets the cycle number in newTheatreChase()
int TCColor = 0;               //sets the color in newTheatreChase()
int l = 0;                     //sets the color value to send to Wheel in newTheatreChaseRainbow() and newRainbow()
int m = 0;                     //sets the color value in newRainbowCycle()
int n = 2;                     //sets the pixel number in cyclonChaser()
int breather = 0;              //sets the brightness value in breather()
boolean dir = true;            //sets the direction in breather()-breathing in or out, and cylonChaser()-left or right
boolean beat = true;           //sets the beat cycle in heartbeat()
int beats = 0;                 //sets the beat number in heartbeat()
int brightness = 150;          //sets the default brightness value
int o = 0;                     //christmas LED value
int q = 5;                     // values for the All() function
uint32_t lastAllColor = 0;     // last color displayed in the All() function

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }

  // attempt to connect to WiFi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();

  // You can provide a unique client ID, if not set the library uses Arduino-millis()
  // Each client must have a unique client ID
  mqttClient.setId("neopixel1");

  // You can provide a username and password for authentication
  // mqttClient.setUsernamePassword("username", "password");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1)
      ;
  }

  Serial.println("You're connected to the MQTT broker!");
  Serial.println();

  // pins
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pixels.begin();                    //starts the neopixels
  pixels.setBrightness(brightness);  // sets the inital brightness of the neopixels
  NeoState[5] = true;
}

void loop() {
  // call poll() regularly to allow the library to send MQTT keep alives which
  // avoids being disconnected by the broker
  mqttClient.poll();

  // to avoid having delays in loop, we'll use the strategy from BlinkWithoutDelay
  // see: File -> Examples -> 02.Digital -> BlinkWithoutDelay for more info
  unsigned long currentMillis = millis();
  distance = ultrasonic.read();

  if (currentMillis - previousDistanceMillis >= interval) {
    // save the last time a message was sent
    previousDistanceMillis = currentMillis;
    //digitalWrite(trig , HIGH);
    //delayMicroseconds(1000);
    //digitalWrite(trig , HIGH);
    //duration = pulseIn(echo , HIGH);
    //distance = (duration/2) / 28.5 ;

    if (distance <= 50 && distance > 0) {
      Serial.print("distance between 0 and 50: ");
      Serial.println(distance);
      digitalWrite(LED1, LOW);
      digitalWrite(LED2, HIGH);
      //Serial.println(topic);
      mqttClient.beginMessage(topic);
      mqttClient.print("1");
      mqttClient.endMessage();
      isOn = true;

    } else {

      if (isOn) {
        Serial.println("sending off message");
        mqttClient.beginMessage(topic);
        mqttClient.print("0");
        mqttClient.endMessage();
        isOn = false;
      }

      digitalWrite(LED1, HIGH);
      // Serial.println("neopixel");
      digitalWrite(LED2, LOW);
    }

    Serial.println();

    count++;
  }
  // Serial.println("neopixel");
  NeoPixModes();  //run the NeoPixModes function
}
uint32_t Wheel(byte WheelPos)  //neopixel wheel function, pick from 256 colors
{
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void writeLEDS(byte R, byte G, byte B)  //basic write colors to the neopixels with RGB values
{
  for (int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B));
  }
  pixels.show();
}
void writeLEDS(byte R, byte G, byte B, byte bright)  //same as above with brightness added
{
  float fR = (R / 255) * bright;
  float fG = (G / 255) * bright;
  float fB = (B / 255) * bright;
  for (int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B));
  }
  pixels.show();
}
void writeLEDS(byte R, byte G, byte B, byte bright, byte LED)  // same as above only with individual LEDS
{
  float fR = (R / 255) * bright;
  float fG = (G / 255) * bright;
  float fB = (B / 255) * bright;
  pixels.setPixelColor(LED, pixels.Color(R, G, B));
  pixels.show();
}
unsigned int RGBValue(const char* s)  //converts the value to an RGB value
{
  unsigned int result = 0;
  int c;
  if ('0' == *s && 'x' == *(s + 1)) {
    s += 2;
    while (*s) {
      result = result << 4;
      if (c = (*s - '0'), (c >= 0 && c <= 9)) result |= c;
      else if (c = (*s - 'A'), (c >= 0 && c <= 5)) result |= (c + 10);
      else if (c = (*s - 'a'), (c >= 0 && c <= 5)) result |= (c + 10);
      else break;
      ++s;
    }
  }
  return result;
}

uint8_t splitColor(uint32_t c, char value) {
  switch (value) {
    case 'r': return (uint8_t)(c >> 16);
    case 'g': return (uint8_t)(c >> 8);
    case 'b': return (uint8_t)(c >> 0);
    default: return 0;
  }
}
void NeoPixModes() {
  if (NeoState[0]) {
    writeLEDS(255, 0, 0);  //write RED to all pixels
  } else if (NeoState[1]) {
    newColorWipe();
  } else if (NeoState[2]) {
    writeLEDS(0, 255, 0);  //write GREEN to all pixels
  } else if (NeoState[3]) {
    newTheatreChase();
  } else if (NeoState[4]) {
    writeLEDS(0, 0, 255);  //write BLUE to all pixels
  } else if (NeoState[5]) {
    // Serial.println("rainbow");
    newRainbow();
  } else if (NeoState[6]) {
    writeLEDS(255, 255, 255);
  } else if (NeoState[7]) {
    newTheatreChaseRainbow();
  } else if (NeoState[8]) {
    cylonChaser();
  } else if (NeoState[9]) {
    newRainbowCycle();
  } else if (NeoState[10]) {
    breathing();
  } else if (NeoState[11]) {
    heartbeat();
  } else if (NeoState[12]) {
    christmasChase();
  } else if (NeoState[13]) {
    ALL();
  } else if (NeoState[14]) {
    writeLEDS(0, 0, 0);  //sets all the pixels to off;
  }
}

/*
 * NEOPIXEL FUNCTIONS
 */

void ALL() {
  if (millis() - lastAllCycle > 60000) {
    q++;
    if ((q < 5) || (q > 14)) {
      q = 5;
    }
    lastAllCycle = millis();
  }
  if (q == 5)  // if the option has been selected keep running the function for that option
  {
    newColorWipe();
  }
  if (q == 6) {
    newTheatreChase();
  }
  if (q == 7) {
    newRainbow();
  }
  if (q == 8) {
    newTheatreChaseRainbow();
  }
  if (q == 9) {
    colorCycler();
    cylonChaser();
  }
  if (q == 10) {
    newRainbowCycle();
  }
  if (q == 11) {
    colorCycler();
    breathing();
  }
  if (q == 12) {
    colorCycler();
    heartbeat();
  }
  if (q == 13) {
    christmasChase();
  }
}
void colorCycler() {
  if (millis() - previousColorMillis > interval) {
    lastColor++;
    if (lastColor > 255) {
      lastColor = 0;
    }
    uint32_t newColor = Wheel(lastColor);
    activeColor[0] = splitColor(newColor, 'r');
    activeColor[1] = splitColor(newColor, 'g');
    activeColor[2] = splitColor(newColor, 'b');
    previousColorMillis = millis();
  }
}
void christmasChase() {
  if (millis() - previousMillis > interval * 10)  //if the time between the function being last run is greater than intervel * 2 - run it
  {
    for (int q = 0; q < NUMPIXELS + 4; q++) {
      pixels.setPixelColor(q, pixels.Color(255, 0, 0));
    }
    if (o < 4) {
      for (int p = o; p < NUMPIXELS + 4; p = p + 4) {
        if (p == 0) {
          pixels.setPixelColor(p, pixels.Color(0, 255, 0));
        } else if ((p > 0) && (p < NUMPIXELS + 4)) {
          pixels.setPixelColor(p, pixels.Color(0, 255, 0));
          pixels.setPixelColor(p - 1, pixels.Color(0, 255, 0));
        }
        if ((p == 2) && (NUMPIXELS % 4) == 2) {
          pixels.setPixelColor(NUMPIXELS - 1, pixels.Color(0, 255, 0));
        }
      }
      pixels.show();
      o++;
    }
    if (o >= 4)
      o = 0;
    previousMillis = millis();
  }
}
void heartbeat() {
#if defined DEBUG
  Serial.print("testinterval");
  Serial.println(millis() - previousMillis);
#endif
  if (millis() - previousMillis > interval * 2)  //if the time between the function being last run is greater than intervel * 2 - run it
  {
    if ((beat == true) && (beats == 0) && (millis() - previousMillis > interval * 7))  //if the beat is on and it's the first beat (beats==0) and the time between them is enough
    {
      for (int h = 50; h <= 255; h = h + 15)  //turn on the pixels at 50 and bring it up to 255 in 15 level increments
      {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);
        delay(3);
      }
      beat = false;               //sets the next beat to off
      previousMillis = millis();  //starts the timer again

    } else if ((beat == false) && (beats == 0))  //if the beat is off and the beat cycle is still in the first beat
    {
      for (int h = 255; h >= 0; h = h - 15)  //turn off the pixels
      {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);
        delay(3);
      }
      beat = true;  //sets the beat to On
      beats = 1;    //sets the next beat to the second beat
      previousMillis = millis();
    } else if ((beat == true) && (beats == 1) && (millis() - previousMillis > interval * 2))  //if the beat is on and it's the second beat and the interval is enough
    {
      for (int h = 50; h <= 255; h = h + 15) {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);  //turn on the pixels
        delay(3);
      }
      beat = false;  //sets the next beat to off
      previousMillis = millis();
    } else if ((beat == false) && (beats == 1))  //if the beat is off and it's the second beat
    {
      for (int h = 255; h >= 0; h = h - 15) {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);  //turn off the pixels
        delay(3);
      }
      beat = true;  //sets the next beat to on
      beats = 0;    //starts the sequence again
      previousMillis = millis();
    }
#if defined DEBUG
    Serial.print("previousMillis:");
    Serial.println(previousMillis);
#endif
  }
}
void breathing() {
  if (millis() - previousMillis > interval * 2)  //if the timer has reached its delay value
  {
    writeLEDS((activeColor[0] / 255) * breather, (activeColor[1] / 255) * breather, (activeColor[2] / 255) * breather);  //write the leds to the color and brightness level
    if (dir == true)                                                                                                     //if the lights are coming on
    {
      if (breather < 255)  //once the value is less than 255
      {
        breather = breather + 15;  //adds 15 to the brightness level for the next time
      } else if (breather >= 255)  //if the brightness is greater or equal to 255
      {
        dir = false;  //sets the direction to false
      }
    }
    if (dir == false)  //if the lights are going off
    {
      if (breather > 0) {
        breather = breather - 15;  //takes 15 away from the brightness level
      } else if (breather <= 0)    //if the brightness level is nothing
        dir = true;                //changes the direction again to on
    }
    previousMillis = millis();
  }
}
void cylonChaser() {
  if (millis() - previousMillis > interval * 2 / 3) {
    for (int h = 0; h < pixels.numPixels(); h++) {
      pixels.setPixelColor(h, 0);  //sets all pixels to off
    }
    if (pixels.numPixels() <= 10)  //if the number of pixels in the strip is 10 or less only activate 3 leds in the strip
    {
      pixels.setPixelColor(n, pixels.Color(activeColor[0], activeColor[1], activeColor[2]));                                             //sets the main pixel to full brightness
      pixels.setPixelColor(n + 1, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));  //sets the surrounding pixels brightness to 50
      pixels.setPixelColor(n - 1, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      if (dir == true)  //if the pixels are going up in value
      {
        if (n < (pixels.numPixels() - 1))  //if the pixels are moving forward and havent reach the end of the strip "-1" to allow for the surrounding pixels
        {
          n++;                                     //increase N ie move one more forward the next time
        } else if (n >= (pixels.numPixels() - 1))  //if the pixels have reached the end of the strip
        {
          dir = false;  //change the direction
        }
      }
      if (dir == false)  //if the pixels are going down in value
      {
        if (n > 1)  //if the pixel number is greater than 1 (to allow for the surrounding pixels)
        {
          n--;              //decrease the active pixel number
        } else if (n <= 1)  //if the pixel number has reached 1
        {
          dir = true;  //change the direction
        }
      }
    }
    if ((pixels.numPixels() > 10) && (pixels.numPixels() <= 20))  //if there are between 11 and 20 pixels in the strip add 2 pixels on either side of the main pixel
    {
      pixels.setPixelColor(n, pixels.Color(activeColor[0], activeColor[1], activeColor[2]));  //same as above only with 2 pixels either side
      pixels.setPixelColor(n + 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n + 2, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      pixels.setPixelColor(n - 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n - 2, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      if (dir == true) {
        if (n < (pixels.numPixels() - 2)) {
          n++;
        } else if (n >= (pixels.numPixels() - 2)) {
          dir = false;
        }
      }
      if (dir == false) {
        if (n > 2) {
          n--;
        } else if (n <= 2) {
          dir = true;
        }
      }
    }
    if (pixels.numPixels() > 20)  //if there are more than 20 pixels in the strip add 3 pixels either side of the main pixel
    {
      pixels.setPixelColor(n, pixels.Color((activeColor[0] / 255) * 255, (activeColor[1] / 255) * 255, (activeColor[2] / 255) * 255));
      pixels.setPixelColor(n + 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n + 2, pixels.Color((activeColor[0] / 255) * 100, (activeColor[1] / 255) * 100, (activeColor[2] / 255) * 100));
      pixels.setPixelColor(n + 3, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      pixels.setPixelColor(n - 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n - 2, pixels.Color((activeColor[0] / 255) * 100, (activeColor[1] / 255) * 100, (activeColor[2] / 255) * 100));
      pixels.setPixelColor(n - 3, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      if (dir == true) {
        if (n < (pixels.numPixels() - 3)) {
          n++;
        } else if (n >= (pixels.numPixels() - 3)) {
          dir = false;
        }
      }
      if (dir == false) {
        if (n > 3) {
          n--;
        } else if (n <= 3) {
          dir = true;
        }
      }
    }
    pixels.show();  //show the pixels
    previousMillis = millis();
  }
}
void newTheatreChaseRainbow() {
  if (millis() - previousMillis > interval * 2) {
    for (int h = 0; h < pixels.numPixels(); h = h + 3) {
      pixels.setPixelColor(h + (j - 1), 0);  //turn every third pixel off from the last cycle
      pixels.setPixelColor(NUMPIXELS - 1, 0);
    }
    for (int h = 0; h < pixels.numPixels(); h = h + 3) {
      pixels.setPixelColor(h + j, Wheel((h + l) % 255));  //turn every third pixel on and cycle the color
    }
    pixels.show();
    j++;
    if (j >= 3)
      j = 0;
    l++;
    if (l >= 256)
      l = 0;
    previousMillis = millis();
  }
}
void newRainbowCycle() {
  if (millis() - previousMillis > interval * 2) {
    for (int h = 0; h < pixels.numPixels(); h++) {
      pixels.setPixelColor(h, Wheel(((h * 256 / pixels.numPixels()) + m) & 255));
    }
    m++;
    if (m >= 256 * 5)
      m = 0;
    pixels.show();
    previousMillis = millis();
  }
}
void newRainbow() {
  if (millis() - previousMillis > interval * 2) {
    for (int h = 0; h < pixels.numPixels(); h++) {
      pixels.setPixelColor(h, Wheel((h + l) & 255));
    }
    l++;
    if (l >= 256)
      l = 0;
    pixels.show();
    previousMillis = millis();
  }
}
void newTheatreChase() {
  if (millis() - previousMillis > interval * 2) {
    uint32_t color;
    int k = j - 3;
    j = i;
    while (k >= 0) {
      pixels.setPixelColor(k, 0);
      k = k - 3;
    }
    if (TCColor == 0) {
      color = pixels.Color(255, 0, 0);
    } else if (TCColor == 1) {
      color = pixels.Color(0, 255, 0);
    } else if (TCColor == 2) {
      color = pixels.Color(0, 0, 255);
    } else if (TCColor == 3) {
      color = pixels.Color(255, 255, 255);
    }
    while (j < NUMPIXELS) {
      pixels.setPixelColor(j, color);
      j = j + 3;
    }
    pixels.show();
    if (cycle == 10) {
      TCColor++;
      cycle = 0;
      if (TCColor == 4)
        TCColor = 0;
    }
    i++;
    if (i >= 3) {
      i = 0;
      cycle++;
    }
    previousMillis = millis();
  }
}
void newColorWipe() {
  if (millis() - previousMillis > interval * 2) {
    uint32_t color;
    if (CWColor == 0) {
      color = pixels.Color(255, 0, 0);
    } else if (CWColor == 1) {
      color = pixels.Color(0, 255, 0);
    } else if (CWColor == 2) {
      color = pixels.Color(0, 0, 255);
    }
    pixels.setPixelColor(i, color);
    pixels.show();
    i++;
    if (i == NUMPIXELS) {
      i = 0;
      CWColor++;
      if (CWColor == 3)
        CWColor = 0;
    }
    previousMillis = millis();
  }
}

Code for Receiver:

/*
  ArduinoMqttClient - WiFi Simple Receive

  This example connects to a MQTT broker and subscribes to a single topic.
  When a message is received it prints the message to the Serial Monitor.

  The circuit:
  - Arduino MKR 1000, MKR 1010 or Uno WiFi Rev2 board

  This example code is in the public domain.
*/

#include <ArduinoMqttClient.h>
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
#include <WiFiNINA.h>
#elif defined(ARDUINO_SAMD_MKR1000)
#include <WiFi101.h>
#elif defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_GIGA)
#include <WiFi.h>
#endif

#include "arduino_secrets.h"

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__

#include <avr/power.h>  // Required for 16 MHz Adafruit Trinket
#endif

// /// led code
#define LED_PIN 6

// // How many NeoPixels are attached to the Arduino?
// #define LED_COUNT 55

// // Declare our NeoPixel strip object:
// Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// #define PIN            12 //sets the pin on which the neopixels are connected
#define NUMPIXELS 55      //defines the number of pixels in the strip
#define interval 5        //defines the delay interval between running the functions
#define wifiRetryTimes 0  //number of times to try the wifi router before going into AP mode (set to 0 if AP only)
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

uint32_t red = pixels.Color(255, 0, 0);
uint32_t blue = pixels.Color(0, 0, 255);
uint32_t green = pixels.Color(0, 255, 0);
uint32_t pixelColour;
uint32_t lastColor;
float activeColor[] = { 255, 0, 0 };  //sets the default color to red

boolean NeoState[] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, true };  //Active Neopixel Function (off by default)

int neopixMode = 0;            //sets a mode to run each of the functions
long previousMillis = 0;       // a long value to store the millis()
long lastAllCycle = 0;         // last cycle in the ALL() function
long previousColorMillis = 0;  // timer for the last color change
int i = 0;                     //sets the pixel number in newTheatreChase() and newColorWipe()
int CWColor = 0;               //sets the newColorWipe() color value 0=Red, 1=Green, 2=Blue
int j;                         //sets the pixel to skip in newTheatreChase() and newTheatreChaseRainbow()
int cycle = 0;                 //sets the cycle number in newTheatreChase()
int TCColor = 0;               //sets the color in newTheatreChase()
int l = 0;                     //sets the color value to send to Wheel in newTheatreChaseRainbow() and newRainbow()
int m = 0;                     //sets the color value in newRainbowCycle()
int n = 2;                     //sets the pixel number in cyclonChaser()
int breather = 0;              //sets the brightness value in breather()
boolean dir = true;            //sets the direction in breather()-breathing in or out, and cylonChaser()-left or right
boolean beat = true;           //sets the beat cycle in heartbeat()
int beats = 0;                 //sets the beat number in heartbeat()
int brightness = 150;          //sets the default brightness value
int o = 0;                     //christmas LED value
int q = 5;                     // values for the All() function
uint32_t lastAllColor = 0;     // last color displayed in the All() function

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;  // your network SSID (name)
char pass[] = SECRET_PASS;  // your network password (use for WPA, or use as key for WEP)

// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate
//    flashed in the WiFi module.

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "23.21.151.236";
int port = 1883;
const char topic[] = "ultrasonic";

const int LED1 = 11;
bool ledsShouldBeOn = false;

void turnLEDSOn() {
  digitalWrite(LED1, HIGH);
  // Serial.println("turnLEDSOn");
  NeoState[5] = true;
}

void turnLEDSOff() {
  digitalWrite(LED1, LOW);
  // Serial.println("turnLEDSOff");
  // Serial.println("low");
  // colorWipe(strip.Color(  0,   0, 0), 1); // clears the screen
  NeoState[5] = false;
  writeLEDS(0, 0, 0);  //sets all the pixels to off
}

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }

  // attempt to connect to WiFi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();

  // You can provide a unique client ID, if not set the library uses Arduino-millis()
  // Each client must have a unique client ID
  mqttClient.setId("neopixel2");

  // You can provide a username and password for authentication
  // mqttClient.setUsernamePassword("username", "password");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1)
      ;
  }

  Serial.println("You're connected to the MQTT broker!");
  Serial.println();

  Serial.print("Subscribing to topic: ");
  Serial.println(topic);
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe(topic);
  // set the message receive callback
  mqttClient.onMessage(onMqttMessage);

  // topics can be unsubscribed using:
  // mqttClient.unsubscribe(topic);

  Serial.print("Waiting for messages on topic: ");
  Serial.println(topic);
  Serial.println();
  pinMode(LED1, OUTPUT);
  digitalWrite(LED1, LOW);

  pixels.begin();                    //starts the neopixels
  pixels.setBrightness(brightness);  // sets the inital brightness of the neopixels
  NeoState[5] = true;
}

void loop() {
  int messageSize = mqttClient.parseMessage();

  if (messageSize) {
    // we received a message, print out the topic and contents
    Serial.print("Received a message with topic '");
    Serial.print(mqttClient.messageTopic());
    Serial.print("', length ");
    Serial.print(messageSize);
    Serial.println(" bytes:");
  }
  if (ledsShouldBeOn) {
    turnLEDSOn();
  } else {
    turnLEDSOff();
  }
  NeoPixModes();  //run the NeoPixModes function
}

void onMqttMessage(int messageSize) {
  // we received a message, print out the topic and contents
  // Serial.print("Received a message with topic '");
  // Serial.print(mqttClient.messageTopic());
  // Serial.print("', duplicate = ");
  // Serial.print(mqttClient.messageDup() ? "true" : "false");
  // Serial.print(", QoS = ");
  // Serial.print(mqttClient.messageQoS());
  // Serial.print(", retained = ");
  // Serial.print(mqttClient.messageRetain() ? "true" : "false");
  // Serial.print("', length ");
  // Serial.print(messageSize);
  // Serial.println(" bytes:");

  // use the Stream interface to print the contents
  char value;
  while (mqttClient.available()) {
    value = (char)mqttClient.read();
    // Serial.print((char)mqttClient.read());
  }

  Serial.print("value: ");
  Serial.println(value);

  if (value == '1') {
    digitalWrite(LED1, HIGH);
    Serial.println("high");
    ledsShouldBeOn = true;
    // rainbow(10);
    // NeoState[5] = true;
  } else {
    digitalWrite(LED1, LOW);
    Serial.println("low");
    // // colorWipe(strip.Color(  0,   0, 0), 1); // clears the screen
    // NeoState[5] = false;
    // writeLEDS(0, 0, 0);  //sets all the pixels to off
    ledsShouldBeOn = false;
  }
}

uint32_t Wheel(byte WheelPos)  //neopixel wheel function, pick from 256 colors
{
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void writeLEDS(byte R, byte G, byte B)  //basic write colors to the neopixels with RGB values
{
  for (int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B));
  }
  pixels.show();
}
void writeLEDS(byte R, byte G, byte B, byte bright)  //same as above with brightness added
{
  float fR = (R / 255) * bright;
  float fG = (G / 255) * bright;
  float fB = (B / 255) * bright;
  for (int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B));
  }
  pixels.show();
}
void writeLEDS(byte R, byte G, byte B, byte bright, byte LED)  // same as above only with individual LEDS
{
  float fR = (R / 255) * bright;
  float fG = (G / 255) * bright;
  float fB = (B / 255) * bright;
  pixels.setPixelColor(LED, pixels.Color(R, G, B));
  pixels.show();
}
unsigned int RGBValue(const char* s)  //converts the value to an RGB value
{
  unsigned int result = 0;
  int c;
  if ('0' == *s && 'x' == *(s + 1)) {
    s += 2;
    while (*s) {
      result = result << 4;
      if (c = (*s - '0'), (c >= 0 && c <= 9)) result |= c;
      else if (c = (*s - 'A'), (c >= 0 && c <= 5)) result |= (c + 10);
      else if (c = (*s - 'a'), (c >= 0 && c <= 5)) result |= (c + 10);
      else break;
      ++s;
    }
  }
  return result;
}

uint8_t splitColor(uint32_t c, char value) {
  switch (value) {
    case 'r': return (uint8_t)(c >> 16);
    case 'g': return (uint8_t)(c >> 8);
    case 'b': return (uint8_t)(c >> 0);
    default: return 0;
  }
}
void NeoPixModes() {
  if (NeoState[0]) {
    writeLEDS(255, 0, 0);  //write RED to all pixels
  } else if (NeoState[1]) {
    newColorWipe();
  } else if (NeoState[2]) {
    writeLEDS(0, 255, 0);  //write GREEN to all pixels
  } else if (NeoState[3]) {
    newTheatreChase();
  } else if (NeoState[4]) {
    writeLEDS(0, 0, 255);  //write BLUE to all pixels
  } else if (NeoState[5]) {
    // Serial.println("rainbow");
    newRainbow();
  } else if (NeoState[6]) {
    writeLEDS(255, 255, 255);
  } else if (NeoState[7]) {
    newTheatreChaseRainbow();
  } else if (NeoState[8]) {
    cylonChaser();
  } else if (NeoState[9]) {
    newRainbowCycle();
  } else if (NeoState[10]) {
    breathing();
  } else if (NeoState[11]) {
    heartbeat();
  } else if (NeoState[12]) {
    christmasChase();
  } else if (NeoState[13]) {
    ALL();
  } else if (NeoState[14]) {
    writeLEDS(0, 0, 0);  //sets all the pixels to off;
  }
}

/*
 * NEOPIXEL FUNCTIONS
 */

void ALL() {
  if (millis() - lastAllCycle > 60000) {
    q++;
    if ((q < 5) || (q > 14)) {
      q = 5;
    }
    lastAllCycle = millis();
  }
  if (q == 5)  // if the option has been selected keep running the function for that option
  {
    newColorWipe();
  }
  if (q == 6) {
    newTheatreChase();
  }
  if (q == 7) {
    newRainbow();
  }
  if (q == 8) {
    newTheatreChaseRainbow();
  }
  if (q == 9) {
    colorCycler();
    cylonChaser();
  }
  if (q == 10) {
    newRainbowCycle();
  }
  if (q == 11) {
    colorCycler();
    breathing();
  }
  if (q == 12) {
    colorCycler();
    heartbeat();
  }
  if (q == 13) {
    christmasChase();
  }
}
void colorCycler() {
  if (millis() - previousColorMillis > interval) {
    lastColor++;
    if (lastColor > 255) {
      lastColor = 0;
    }
    uint32_t newColor = Wheel(lastColor);
    activeColor[0] = splitColor(newColor, 'r');
    activeColor[1] = splitColor(newColor, 'g');
    activeColor[2] = splitColor(newColor, 'b');
    previousColorMillis = millis();
  }
}
void christmasChase() {
  if (millis() - previousMillis > interval * 10)  //if the time between the function being last run is greater than intervel * 2 - run it
  {
    for (int q = 0; q < NUMPIXELS + 4; q++) {
      pixels.setPixelColor(q, pixels.Color(255, 0, 0));
    }
    if (o < 4) {
      for (int p = o; p < NUMPIXELS + 4; p = p + 4) {
        if (p == 0) {
          pixels.setPixelColor(p, pixels.Color(0, 255, 0));
        } else if ((p > 0) && (p < NUMPIXELS + 4)) {
          pixels.setPixelColor(p, pixels.Color(0, 255, 0));
          pixels.setPixelColor(p - 1, pixels.Color(0, 255, 0));
        }
        if ((p == 2) && (NUMPIXELS % 4) == 2) {
          pixels.setPixelColor(NUMPIXELS - 1, pixels.Color(0, 255, 0));
        }
      }
      pixels.show();
      o++;
    }
    if (o >= 4)
      o = 0;
    previousMillis = millis();
  }
}
void heartbeat() {
#if defined DEBUG
  Serial.print("testinterval");
  Serial.println(millis() - previousMillis);
#endif
  if (millis() - previousMillis > interval * 2)  //if the time between the function being last run is greater than intervel * 2 - run it
  {
    if ((beat == true) && (beats == 0) && (millis() - previousMillis > interval * 7))  //if the beat is on and it's the first beat (beats==0) and the time between them is enough
    {
      for (int h = 50; h <= 255; h = h + 15)  //turn on the pixels at 50 and bring it up to 255 in 15 level increments
      {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);
        delay(3);
      }
      beat = false;               //sets the next beat to off
      previousMillis = millis();  //starts the timer again

    } else if ((beat == false) && (beats == 0))  //if the beat is off and the beat cycle is still in the first beat
    {
      for (int h = 255; h >= 0; h = h - 15)  //turn off the pixels
      {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);
        delay(3);
      }
      beat = true;  //sets the beat to On
      beats = 1;    //sets the next beat to the second beat
      previousMillis = millis();
    } else if ((beat == true) && (beats == 1) && (millis() - previousMillis > interval * 2))  //if the beat is on and it's the second beat and the interval is enough
    {
      for (int h = 50; h <= 255; h = h + 15) {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);  //turn on the pixels
        delay(3);
      }
      beat = false;  //sets the next beat to off
      previousMillis = millis();
    } else if ((beat == false) && (beats == 1))  //if the beat is off and it's the second beat
    {
      for (int h = 255; h >= 0; h = h - 15) {
        writeLEDS((activeColor[0] / 255) * h, (activeColor[1] / 255) * h, (activeColor[2] / 255) * h);  //turn off the pixels
        delay(3);
      }
      beat = true;  //sets the next beat to on
      beats = 0;    //starts the sequence again
      previousMillis = millis();
    }
#if defined DEBUG
    Serial.print("previousMillis:");
    Serial.println(previousMillis);
#endif
  }
}
void breathing() {
  if (millis() - previousMillis > interval * 2)  //if the timer has reached its delay value
  {
    writeLEDS((activeColor[0] / 255) * breather, (activeColor[1] / 255) * breather, (activeColor[2] / 255) * breather);  //write the leds to the color and brightness level
    if (dir == true)                                                                                                     //if the lights are coming on
    {
      if (breather < 255)  //once the value is less than 255
      {
        breather = breather + 15;  //adds 15 to the brightness level for the next time
      } else if (breather >= 255)  //if the brightness is greater or equal to 255
      {
        dir = false;  //sets the direction to false
      }
    }
    if (dir == false)  //if the lights are going off
    {
      if (breather > 0) {
        breather = breather - 15;  //takes 15 away from the brightness level
      } else if (breather <= 0)    //if the brightness level is nothing
        dir = true;                //changes the direction again to on
    }
    previousMillis = millis();
  }
}
void cylonChaser() {
  if (millis() - previousMillis > interval * 2 / 3) {
    for (int h = 0; h < pixels.numPixels(); h++) {
      pixels.setPixelColor(h, 0);  //sets all pixels to off
    }
    if (pixels.numPixels() <= 10)  //if the number of pixels in the strip is 10 or less only activate 3 leds in the strip
    {
      pixels.setPixelColor(n, pixels.Color(activeColor[0], activeColor[1], activeColor[2]));                                             //sets the main pixel to full brightness
      pixels.setPixelColor(n + 1, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));  //sets the surrounding pixels brightness to 50
      pixels.setPixelColor(n - 1, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      if (dir == true)  //if the pixels are going up in value
      {
        if (n < (pixels.numPixels() - 1))  //if the pixels are moving forward and havent reach the end of the strip "-1" to allow for the surrounding pixels
        {
          n++;                                     //increase N ie move one more forward the next time
        } else if (n >= (pixels.numPixels() - 1))  //if the pixels have reached the end of the strip
        {
          dir = false;  //change the direction
        }
      }
      if (dir == false)  //if the pixels are going down in value
      {
        if (n > 1)  //if the pixel number is greater than 1 (to allow for the surrounding pixels)
        {
          n--;              //decrease the active pixel number
        } else if (n <= 1)  //if the pixel number has reached 1
        {
          dir = true;  //change the direction
        }
      }
    }
    if ((pixels.numPixels() > 10) && (pixels.numPixels() <= 20))  //if there are between 11 and 20 pixels in the strip add 2 pixels on either side of the main pixel
    {
      pixels.setPixelColor(n, pixels.Color(activeColor[0], activeColor[1], activeColor[2]));  //same as above only with 2 pixels either side
      pixels.setPixelColor(n + 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n + 2, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      pixels.setPixelColor(n - 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n - 2, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      if (dir == true) {
        if (n < (pixels.numPixels() - 2)) {
          n++;
        } else if (n >= (pixels.numPixels() - 2)) {
          dir = false;
        }
      }
      if (dir == false) {
        if (n > 2) {
          n--;
        } else if (n <= 2) {
          dir = true;
        }
      }
    }
    if (pixels.numPixels() > 20)  //if there are more than 20 pixels in the strip add 3 pixels either side of the main pixel
    {
      pixels.setPixelColor(n, pixels.Color((activeColor[0] / 255) * 255, (activeColor[1] / 255) * 255, (activeColor[2] / 255) * 255));
      pixels.setPixelColor(n + 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n + 2, pixels.Color((activeColor[0] / 255) * 100, (activeColor[1] / 255) * 100, (activeColor[2] / 255) * 100));
      pixels.setPixelColor(n + 3, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      pixels.setPixelColor(n - 1, pixels.Color((activeColor[0] / 255) * 150, (activeColor[1] / 255) * 150, (activeColor[2] / 255) * 150));
      pixels.setPixelColor(n - 2, pixels.Color((activeColor[0] / 255) * 100, (activeColor[1] / 255) * 100, (activeColor[2] / 255) * 100));
      pixels.setPixelColor(n - 3, pixels.Color((activeColor[0] / 255) * 50, (activeColor[1] / 255) * 50, (activeColor[2] / 255) * 50));
      if (dir == true) {
        if (n < (pixels.numPixels() - 3)) {
          n++;
        } else if (n >= (pixels.numPixels() - 3)) {
          dir = false;
        }
      }
      if (dir == false) {
        if (n > 3) {
          n--;
        } else if (n <= 3) {
          dir = true;
        }
      }
    }
    pixels.show();  //show the pixels
    previousMillis = millis();
  }
}
void newTheatreChaseRainbow() {
  if (millis() - previousMillis > interval * 2) {
    for (int h = 0; h < pixels.numPixels(); h = h + 3) {
      pixels.setPixelColor(h + (j - 1), 0);  //turn every third pixel off from the last cycle
      pixels.setPixelColor(NUMPIXELS - 1, 0);
    }
    for (int h = 0; h < pixels.numPixels(); h = h + 3) {
      pixels.setPixelColor(h + j, Wheel((h + l) % 255));  //turn every third pixel on and cycle the color
    }
    pixels.show();
    j++;
    if (j >= 3)
      j = 0;
    l++;
    if (l >= 256)
      l = 0;
    previousMillis = millis();
  }
}
void newRainbowCycle() {
  if (millis() - previousMillis > interval * 2) {
    for (int h = 0; h < pixels.numPixels(); h++) {
      pixels.setPixelColor(h, Wheel(((h * 256 / pixels.numPixels()) + m) & 255));
    }
    m++;
    if (m >= 256 * 5)
      m = 0;
    pixels.show();
    previousMillis = millis();
  }
}
void newRainbow() {
  if (millis() - previousMillis > interval * 2) {
    for (int h = 0; h < pixels.numPixels(); h++) {
      pixels.setPixelColor(h, Wheel((h + l) & 255));
    }
    l++;
    if (l >= 256)
      l = 0;
    pixels.show();
    previousMillis = millis();
  }
}
void newTheatreChase() {
  if (millis() - previousMillis > interval * 2) {
    uint32_t color;
    int k = j - 3;
    j = i;
    while (k >= 0) {
      pixels.setPixelColor(k, 0);
      k = k - 3;
    }
    if (TCColor == 0) {
      color = pixels.Color(255, 0, 0);
    } else if (TCColor == 1) {
      color = pixels.Color(0, 255, 0);
    } else if (TCColor == 2) {
      color = pixels.Color(0, 0, 255);
    } else if (TCColor == 3) {
      color = pixels.Color(255, 255, 255);
    }
    while (j < NUMPIXELS) {
      pixels.setPixelColor(j, color);
      j = j + 3;
    }
    pixels.show();
    if (cycle == 10) {
      TCColor++;
      cycle = 0;
      if (TCColor == 4)
        TCColor = 0;
    }
    i++;
    if (i >= 3) {
      i = 0;
      cycle++;
    }
    previousMillis = millis();
  }
}
void newColorWipe() {
  if (millis() - previousMillis > interval * 2) {
    uint32_t color;
    if (CWColor == 0) {
      color = pixels.Color(255, 0, 0);
    } else if (CWColor == 1) {
      color = pixels.Color(0, 255, 0);
    } else if (CWColor == 2) {
      color = pixels.Color(0, 0, 255);
    }
    pixels.setPixelColor(i, color);
    pixels.show();
    i++;
    if (i == NUMPIXELS) {
      i = 0;
      CWColor++;
      if (CWColor == 3)
        CWColor = 0;
    }
    previousMillis = millis();
  }
}

// // Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
// void rainbow(int wait) {
//   // Hue of first pixel runs 5 complete loops through the color wheel.
//   // Color wheel has a range of 65536 but it's OK if we roll over, so
//   // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
//   // means we'll make 5*65536/256 = 1280 passes through this loop:
//   for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
//     // strip.rainbow() can take a single argument (first pixel hue) or
//     // optionally a few extras: number of rainbow repetitions (default 1),
//     // saturation and value (brightness) (both 0-255, similar to the
//     // ColorHSV() function, default 255), and a true/false flag for whether
//     // to apply gamma correction to provide 'truer' colors (default true).
//     strip.rainbow(firstPixelHue);
//     // Above line is equivalent to:
//     // strip.rainbow(firstPixelHue, 1, 255, 255, true);
//     strip.show(); // Update strip with new contents
//     delay(wait);  // Pause for a moment
//   }
// }

// void colorWipe(uint32_t color, int wait) {
//   for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
//     strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
//     strip.show();                          //  Update strip to match
//     delay(wait);                           //  Pause for a moment
//   }
// }