 // LED pattern functions
 //
 void solid_color() {
-  // log("solid_color()");
   FastLED.showColor(currentColor);
 }
 
 void center_out() {
-  // log("center_out()");
-  for (int i = 0; i < NUM_LEDS; i++) {
-    if (i <= NUM_LEDS/2+edgesCenterPosition && i >= NUM_LEDS/2-edgesCenterPosition) {
-      leds[i] = currentColor;
-    } else {
-      leds[i] = CRGB::Black;
-    }
-  }
-  FastLED.show();
-
-  edgesCenterPosition = edgesCenterPosition + delta;
-  
-  if (edgesCenterPosition > NUM_LEDS/2+1) {
-    // log("Reverse ... towards pos 0");
-    edgesCenterPosition -= 1;
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    edgesCenterPosition = 0;
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  for (int j=0;j<NUM_LEDS;j++) {
+    for (int i = 0; i < NUM_LEDS; i++) {
+      if (i <= NUM_LEDS/2+edgesCenterPosition && i >= NUM_LEDS/2-edgesCenterPosition) {
+        leds[i] = currentColor;
+      } else {
+        leds[i] = CRGB::Black;
+      }
+    }
+    FastLED.show();
+  
+    edgesCenterPosition = edgesCenterPosition + delta;
+    
+    if (edgesCenterPosition > NUM_LEDS/2+1) {
+      // log("Reverse ... towards pos 0");
+      edgesCenterPosition -= 1;
+      delta = -1;
+      delay(holdTime);
+    } else if (edgesCenterPosition < -1) {
+      // log("Forward we go!");
+      edgesCenterPosition += 1;
+      delta = 1;
+      delay(holdTime);
+    }
+    delay(loopDelay);
+  }
+}
+
+void edges_in() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    edgesCenterPosition = 0;
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  for (int j=0;j<NUM_LEDS;j++) {
+    for (int i = 0; i < NUM_LEDS; i++) {
+      if (i <= edgesCenterPosition || i>=NUM_LEDS-(edgesCenterPosition+1)) {
+        leds[i] = currentColor;
+      } else {
+        leds[i] = CRGB::Black;
+      }
+    }
+    FastLED.show();
+  
+    edgesCenterPosition = edgesCenterPosition + delta;
+    
+    if (edgesCenterPosition > NUM_LEDS/2+1) {
+      // log("Reverse ... towards pos 0");
+      edgesCenterPosition -= 1;
+      delta = -1;
+      delay(holdTime);
+    } else if (edgesCenterPosition < -1) {
+      // log("Forward we go!");
+      edgesCenterPosition += 1;
+      delta = 1;
+      delay(holdTime);
+    }
+    delay(loopDelay);
+  }
+}
+
+
+void slinky_backwards() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    slinkyPosition = NUM_LEDS;
     delta = -1;
-    delay(holdTime);
-  } else if (edgesCenterPosition < -1) {
-    // log("Forward we go!");
-    edgesCenterPosition += 1;
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  for (int j=0;j<NUM_LEDS;j++) {
+    for (int i = 0; i < NUM_LEDS; i++) {
+      if (i > slinkyPosition) {
+        leds[i] = currentColor;
+      } else {
+        leds[i] = CRGB::Black;
+      }
+    }
+    FastLED.show();
+  
+    if (slinkyPosition == NUM_LEDS - 1) {
+      // log("Reverse ... towards pos 0");
+      delta = -1;
+      delay(holdTime);
+    } else if (slinkyPosition == 0) {
+      // log("Forward we go!");
+      delta = 1;
+      delay(holdTime);
+    }
+    slinkyPosition = (slinkyPosition + delta + NUM_LEDS) % NUM_LEDS;
+    delay(loopDelay);
+  }
+}
+
+void slinky() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    slinkyPosition = 1;
     delta = 1;
-    delay(holdTime);
-  }
-}
-
-void edges_in() {
-  for (int i = 0; i < NUM_LEDS; i++) {
-    if (i <= edgesCenterPosition || i>=NUM_LEDS-(edgesCenterPosition+1)) {
-      leds[i] = currentColor;
-    } else {
-      leds[i] = CRGB::Black;
-    }
-  }
-  FastLED.show();
-
-  edgesCenterPosition = edgesCenterPosition + delta;
-  
-  if (edgesCenterPosition > NUM_LEDS/2+1) {
-    // log("Reverse ... towards pos 0");
-    edgesCenterPosition -= 1;
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  for (int j=0;j<NUM_LEDS;j++) {
+    for (int i = 0; i < NUM_LEDS; i++) {
+      if (i <= slinkyPosition) {
+        leds[i] = currentColor;
+      } else {
+        leds[i] = CRGB::Black;
+      }
+    }
+    FastLED.show();
+  
+    if (slinkyPosition == NUM_LEDS - 1) {
+      // log("Reverse ... towards pos 0");
+      delta = -1;
+      delay(holdTime);
+    } else if (slinkyPosition == 0) {
+      // log("Forward we go!");
+      delta = 1;
+      delay(holdTime);
+    }
+    slinkyPosition = (slinkyPosition + delta + NUM_LEDS) % NUM_LEDS;
+    delay(loopDelay);
+  }
+}
+
+void bounce() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    positionRed = 0; 
+    positionWhite = 1;
+    positionBlue = 2;
+    delta = 1;
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  // Set pixel color
+  for (int i=0;i<NUM_LEDS;i++) {
+    leds[positionRed] = currentColor;
+    leds[positionWhite] = currentColor;
+    leds[positionBlue] = currentColor;
+  
+    // Show the pixels
+    FastLED.show();
+  
+    // Set pixels back to Black for the next loop around.
+    leds[positionRed] = CRGB::Black;
+    leds[positionWhite] = CRGB::Black;
+    leds[positionBlue] = CRGB::Black;
+  
+    // Set new position, moving (forward or backward) by delta.
+    // NUM_LEDS is added to the position before doing the modulo
+    // to cover cases where delta is a negative value.
+    if (positionWhite == NUM_LEDS - 1) {
+      // log("Reverse ... towards pos 0");
+      delta = -1;
+    } else if (positionBlue == 1) {
+      // log("Forward we go!");
+      delta = 1;
+    }
+    positionRed = (positionRed + delta + NUM_LEDS) % NUM_LEDS;
+    positionWhite = (positionWhite + delta + NUM_LEDS) % NUM_LEDS;
+    positionBlue = (positionBlue + delta + NUM_LEDS) % NUM_LEDS;
+    delay(loopDelay);
+  }
+}
+
+void bounce_backwards() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    positionRed = NUM_LEDS - 2; 
+    positionWhite = NUM_LEDS - 1;
+    positionBlue = NUM_LEDS;
     delta = -1;
-    delay(holdTime);
-  } else if (edgesCenterPosition < -1) {
-    // log("Forward we go!");
-    edgesCenterPosition += 1;
-    delta = 1;
-    delay(holdTime);
-  }
-}
-
-
-void slinky_backwards() {
-  for (int i = 0; i < NUM_LEDS; i++) {
-    if (i > slinkyPosition) {
-      leds[i] = currentColor;
-    } else {
-      leds[i] = CRGB::Black;
-    }
-  }
-  FastLED.show();
-
-  if (slinkyPosition == NUM_LEDS - 1) {
-    // log("Reverse ... towards pos 0");
-    delta = -1;
-    delay(holdTime);
-  } else if (slinkyPosition == 0) {
-    // log("Forward we go!");
-    delta = 1;
-    delay(holdTime);
-  }
-  slinkyPosition = (slinkyPosition + delta + NUM_LEDS) % NUM_LEDS;
-}
-
-void slinky() {
-  for (int i = 0; i < NUM_LEDS; i++) {
-    if (i <= slinkyPosition) {
-      leds[i] = currentColor;
-    } else {
-      leds[i] = CRGB::Black;
-    }
-  }
-  FastLED.show();
-
-  if (slinkyPosition == NUM_LEDS - 1) {
-    // log("Reverse ... towards pos 0");
-    delta = -1;
-    delay(holdTime);
-  } else if (slinkyPosition == 0) {
-    // log("Forward we go!");
-    delta = 1;
-    delay(holdTime);
-  }
-  slinkyPosition = (slinkyPosition + delta + NUM_LEDS) % NUM_LEDS;
-}
-
-void bounce() {
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
   // Set pixel color
-  leds[positionRed] = currentColor;
-  leds[positionWhite] = currentColor;
-  leds[positionBlue] = currentColor;
-
-  // Show the pixels
-  FastLED.show();
-
-  // Set pixels back to Black for the next loop around.
-  leds[positionRed] = CRGB::Black;
-  leds[positionWhite] = CRGB::Black;
-  leds[positionBlue] = CRGB::Black;
-
-  // Set new position, moving (forward or backward) by delta.
-  // NUM_LEDS is added to the position before doing the modulo
-  // to cover cases where delta is a negative value.
-  if (positionBlue == NUM_LEDS - 1) {
-    // log("Reverse ... towards pos 0");
-    delta = -1;
-  } else if (positionBlue == 1) {
-    // log("Forward we go!");
-    delta = 1;
-  }
-  positionRed = (positionRed + delta + NUM_LEDS) % NUM_LEDS;
-  positionWhite = (positionWhite + delta + NUM_LEDS) % NUM_LEDS;
-  positionBlue = (positionBlue + delta + NUM_LEDS) % NUM_LEDS;
+  for (int i=0;i<NUM_LEDS;i++) {
+    leds[positionRed] = currentColor;
+    leds[positionWhite] = currentColor;
+    leds[positionBlue] = currentColor;
+  
+    // Show the pixels
+    FastLED.show();
+  
+    // Set pixels back to Black for the next loop around.
+    leds[positionRed] = CRGB::Black;
+    leds[positionWhite] = CRGB::Black;
+    leds[positionBlue] = CRGB::Black;
+  
+    // Set new position, moving (forward or backward) by delta.
+    // NUM_LEDS is added to the position before doing the modulo
+    // to cover cases where delta is a negative value.
+    if (positionWhite == NUM_LEDS - 1) {
+      // log("Reverse ... towards pos 0");
+      delta = -1;
+    } else if (positionBlue == 1) {
+      // log("Forward we go!");
+      delta = 1;
+    }
+    positionRed = (positionRed + delta + NUM_LEDS) % NUM_LEDS;
+    positionWhite = (positionWhite + delta + NUM_LEDS) % NUM_LEDS;
+    positionBlue = (positionBlue + delta + NUM_LEDS) % NUM_LEDS;
+    delay(loopDelay);
+  }
+}
+
+void circle() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  // Set pixel color
+  delta = 1;
+  for (int i=0;i<NUM_LEDS;i++) {
+    leds[positionRed] = currentColor;
+    leds[positionWhite] = currentColor;
+    leds[positionBlue] = currentColor;
+  
+    // Show the pixels
+    FastLED.show();
+  
+    // Set pixels back to Black for the next loop around.
+    leds[positionRed] = CRGB::Black;
+    leds[positionWhite] = CRGB::Black;
+    leds[positionBlue] = CRGB::Black;
+  
+    positionRed = (positionRed + delta + NUM_LEDS) % NUM_LEDS;
+    positionWhite = (positionWhite + delta + NUM_LEDS) % NUM_LEDS;
+    positionBlue = (positionBlue + delta + NUM_LEDS) % NUM_LEDS;
+    delay(loopDelay);
+  }
+}
+
+void circle_backwards() {
+  if (!repeat && doneTheNonRepeatingAnimationOnce == true) {
+    return; 
+  }
+  doneTheNonRepeatingAnimationOnce = true;
+  // Set pixel color
+  delta = -1;
+  for (int i=0;i<NUM_LEDS;i++) {
+    leds[positionRed] = currentColor;
+    leds[positionWhite] = currentColor;
+    leds[positionBlue] = currentColor;
+  
+    // Show the pixels
+    FastLED.show();
+  
+    // Set pixels back to Black for the next loop around.
+    leds[positionRed] = CRGB::Black;
+    leds[positionWhite] = CRGB::Black;
+    leds[positionBlue] = CRGB::Black;
+  
+    positionRed = (positionRed + delta + NUM_LEDS) % NUM_LEDS;
+    positionWhite = (positionWhite + delta + NUM_LEDS) % NUM_LEDS;
+    positionBlue = (positionBlue + delta + NUM_LEDS) % NUM_LEDS;
+    delay(loopDelay);
+  }
 }
 
 void off() {
   saveCurrentAnimation("solid_color");
   current_color = "black";
-  loopDelay = origLoopDelay;
-  holdTime = origHoldTime;
+  reset();
 }
 
 void reset() {
   loopDelay = origLoopDelay;
   holdTime = origHoldTime;
+  positionRed = 0; 
+  positionWhite = 1;
+  positionBlue = 2;
+  delta = 1;
+  slinkyPosition = 1;
+  edgesCenterPosition = 0;
+
 }
 
 void handleMqttMessage(char *topic, byte *payload, unsigned int length) {

#define LED_TYPE APA102
#define DATA_PIN 5
#define CLOCK_PIN 4
#define NUM_LEDS 100
#define COLOR_ORDER BGR
#define BRIGHTNESS 50

// ------> CONFIGURE THESE VARIABLES TO MATCH YOUR SETUP  <------
char *hostname = "arch1";                   // The hostname of this device -- eg. thishost.local

boolean connectioWasAlive = true;

char valid_colors[] = "white snow silver gray grey darkgray darkgrey black red crimson darkmagenta darkred magenta maroon orange orangered darkorange yellow gold green lime darkgreen forestgreen cyan darkcyan blue deepskyblue royalblue skyblue darkblue navy blueviolet purple violet indigo darkviolet";
char valid_functions[] = "solid_color center_out edges_in slinky slinky_backwards bounce bounce_backwards circle circle_backwards";
char delim[] = ":";
char *current_color = "black";
std::function<void(void)> currentAnimation;
