Переглянути джерело

CORS, get_config, create and delete cluster

Emil 3 роки тому
батько
коміт
d95e15e06e
7 змінених файлів з 169 додано та 29 видалено
  1. 2 1
      .gitignore
  2. 4 2
      src/Animations.cpp
  3. 4 2
      src/Animations.h
  4. 8 1
      src/LightCluster.cpp
  5. 2 0
      src/LightCluster.h
  6. 2 2
      src/WiFiPass.h
  7. 147 21
      src/main.cpp

+ 2 - 1
.gitignore

@@ -1,4 +1,5 @@
 .pio
 CMakeListsPrivate.txt
 cmake-build-*/
-src/WiFiPass.h
+./src/WiFiPass.h
+WiFiPass.h

+ 4 - 2
src/Animations.cpp

@@ -123,7 +123,7 @@ void Animations::randomColors() {
             lamp->targetW = random(minW, maxW);
 
             lamp->animI = 0;
-            lamp->endTick = random(30, 300); //Between 3 and 30 seconds. TODO add animationSetting3 and 4 fpr this.
+            lamp->endTick = random(animationSetting3, animationSetting4);
 
             lamp->startR = r;
             lamp->startG = g;
@@ -137,6 +137,8 @@ void Animations::setup_randomColors() {
     delayTimeMS = 100;
     animationSetting1 = 0x00000000;
     animationSetting2 = 0xFFFFFFFF;
+    animationSetting3 = 30;
+    animationSetting4 = 300;
     for (int i = 0; i < numLeds; i++) {
         //Serial.println("In loop");
         light *lamp = &lights[i];
@@ -157,7 +159,7 @@ void Animations::setup_randomColors() {
         lamp->targetW = random(minW, maxW);
 
         lamp->animI = 0;
-        lamp->endTick = random(30, 300); //Between 3 and 30 seconds. TODO add animationSetting3 and 4 for this.
+        lamp->endTick = random(animationSetting3, animationSetting4); //Between 3 and 30 seconds. TODO add animationSetting3 and 4 for this.
         //Serial.print("EndTick = ");
         //Serial.println(lamp->endTick);
 

+ 4 - 2
src/Animations.h

@@ -12,8 +12,10 @@ public:
     int animationI;
     int maxAnimationI;
     int delayTimeMS;
-    long animationSetting1;
-    long animationSetting2;
+    long long animationSetting1;
+    long long animationSetting2;
+    long animationSetting3;
+    long animationSetting4;
     int numLeds;
 
     explicit Animations(struct light *lights);

+ 8 - 1
src/LightCluster.cpp

@@ -55,6 +55,7 @@ LightCluster::LightCluster(struct light *incomingLights, int size, int animation
     numLights = size;
     animationObject->numLeds = size;
     lastRun = 0;
+    lights = incomingLights;
     //Serial.println("About to set up animation object");
     this->animationObject = animationObject;
     //Serial.println("Creating lookup");
@@ -66,6 +67,12 @@ LightCluster::LightCluster(struct light *incomingLights, int size, int animation
     runAnimation();
 }
 
+LightCluster::~LightCluster() {
+    delete[] animationObject->lights;
+    delete[] lights;
+    delete[] animationObject;
+}
+
 bool LightCluster::shouldRun() {
     //Serial.println("ShouldRun started");
     if (millis() - lastRun >= animationObject->delayTimeMS) {
@@ -74,4 +81,4 @@ bool LightCluster::shouldRun() {
     }
     //Serial.println("ShouldRun false");
     return false;
-}
+}

+ 2 - 0
src/LightCluster.h

@@ -24,7 +24,9 @@ public:
     void changeAnimation(int newAnimationNumber);
 
     LightCluster(struct light *incomingLights, int size, int animation, Animations *animationObject);
+    ~LightCluster();
 
+    light *lights;
     Animations *animationObject;
 };
 

+ 2 - 2
src/WiFiPass.h

@@ -5,7 +5,7 @@
 #ifndef UNTITLED_WIFIPASS_H
 #define UNTITLED_WIFIPASS_H
 
-const char* ssid = "Tallium 2.4";
-const char* password = "vgjsdsmhds";
+const char* ssid = "SSID HERE";
+const char* password = "PASSWORD HERE";
 
 #endif //UNTITLED_WIFIPASS_H

+ 147 - 21
src/main.cpp

@@ -21,18 +21,28 @@ AsyncWebServer server(80);
 Adafruit_NeoPixel leds(NUM_LEDS, LED_PIN, NEO_WRGB + NEO_KHZ800);
 
 LightCluster *clusters[10];
-int numClusters = 2;
-light lampsInCluster1[7] = {{0,0},{1,0},{3,0},{4,0},{5,0},{6,0},{7,0}};
-Animations animation1(lampsInCluster1);
-LightCluster myCluster(lampsInCluster1, 7, 0, &animation1);
-
-light lampsInCluster2[2] = {{2,0},{8,0}};
-Animations animation2(lampsInCluster2);
-LightCluster myCluster2(lampsInCluster2, 2, 0, &animation2);
+int numClusters = 0;
 
+int occupiedLamps[NUM_LEDS];
+int numOccupiedLamps = 0;
 
 //LightCluster myCluster(lampsInCluster1, 7, 0, Animations(lampsInCluster1));
 
+void updateOccupiedLamps() {
+    for (int & occupiedLamp : occupiedLamps) {
+        occupiedLamp = -1;
+    }
+
+    int numFoundLamps = 0;
+    for (int i = 0; i < numClusters; i++) {
+        for (int lamp = 0; lamp < clusters[i]->numLights; lamp++) {
+            numFoundLamps++;
+            occupiedLamps[clusters[i]->animationObject->lights[lamp].mapped] = i;
+        }
+    }
+    numOccupiedLamps = numFoundLamps;
+}
+
 void connectWiFi() {
     WiFi.mode(WIFI_STA);
     WiFi.begin(ssid, password);
@@ -70,6 +80,7 @@ void connectSDCard() {
     Serial.printf("SD Card Size: %lluMB\n", cardSize);
 }
 
+
 void setupServer() {
     server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
         request->send(SD, "/index.html", "text/html");
@@ -77,6 +88,31 @@ void setupServer() {
 
     server.serveStatic("/", SD, "/");
 
+    server.on("/api/get_config", HTTP_GET, [](AsyncWebServerRequest *request) {
+        AsyncResponseStream *response = request->beginResponseStream("application/json");
+        DynamicJsonDocument json(1024);
+        json["numClusters"] = numClusters;
+        json["clusters"] = DynamicJsonDocument(1024);
+
+        for (int cluster = 0; cluster < numClusters; cluster++) { //    TODO: Send settings too
+            json["clusters"]["numLights"] = clusters[cluster]->numLights;
+            json["clusters"]["animation"] = clusters[cluster]->animationNumber;
+            json["clusters"]["lights"] = DynamicJsonDocument(1024);
+            for (int lamp = 0; lamp < clusters[cluster]->numLights; lamp++) {
+                json["clusters"]["lights"][lamp] = clusters[cluster]->lights[lamp].mapped;
+            }
+        }
+        serializeJson(json, *response);
+        response->addHeader("Access-Control-Allow-Origin","*");
+        response->addHeader("Access-Control-Allow-Headers", "Content-Type, data");
+        response->addHeader("Access-Control-Allow-Methods", "POST, GET");
+        /*response->addHeader("access-control-allow-credentials", "true");
+        response->addHeader("access-control-allow-origin", "*");
+        response->addHeader("access-control-expose-headers", "");*/
+        request->send(response);
+    });
+
+
     server.on("/api/set_config", HTTP_POST, [](AsyncWebServerRequest *request) {
         StaticJsonDocument<400> doc;
         DeserializationError error = deserializeJson(doc, request->header("data"));
@@ -88,32 +124,30 @@ void setupServer() {
         }
 
         for (int i = 0; i < numClusters; i++) {
-            delete[]clusters[i]->animationObject;
             delete[]clusters[i];
         }
 
         int numNewClusters = doc["numClusters"];
         for (int i = 0; i < numNewClusters; i++) {
             int newNumLights = doc["clusters"][i]["numLights"];
-            light newLights[newNumLights];
-            //memset(newLights, 0, newNumLights*sizeof(light));
+            static light *newLights;
+            newLights = (light*) malloc(newNumLights * sizeof(light));
 
             for (int lamp = 0; lamp < newNumLights; lamp++) {
-                newLights[lamp] = {doc["clusters"][i]["lights"]["lamp"], 0};
+                newLights[lamp] = {doc["clusters"][i]["lights"][lamp], 0};
             }
 
             static auto newAnimationObject = new Animations(newLights);
             static auto newLightCluster = new LightCluster(newLights, newNumLights, doc["clusters"][i]["animation"], newAnimationObject);
             clusters[i] = newLightCluster;
+            numClusters = numNewClusters;
+
+            updateOccupiedLamps();
 
             request->send(200, "application/json", "{}");
         }
     });
 
-    server.on("/api/get_config", HTTP_GET, [](AsyncWebServerRequest *request) {
-        //request->send();
-    });
-
     server.on("/api/change_setting", HTTP_POST, [](AsyncWebServerRequest *request) {
         StaticJsonDocument<200> doc;
         DeserializationError error = deserializeJson(doc, request->getHeader("data")->value().c_str());
@@ -125,13 +159,19 @@ void setupServer() {
         }
 
         int cluster = doc["targetCluster"];
-        long value = doc["newValue"];
+        long long value = doc["newValue"];
         if (doc["setting"] == "delayTime") {
             clusters[cluster]->animationObject->delayTimeMS = value;
         } else if (doc["setting"] == "animationSetting1") {
             clusters[cluster]->animationObject->animationSetting1 = value;
         } else if (doc["setting"] == "animationSetting2") {
             clusters[cluster]->animationObject->animationSetting2 = value;
+        } else if (doc["setting"] == "animationSetting3") {
+            clusters[cluster]->animationObject->animationSetting3 = value;
+        } else if (doc["setting"] == "animationSetting4") {
+            clusters[cluster]->animationObject->animationSetting4 = value;
+        } else if (doc["setting"] == "maxAnimationI") {
+            clusters[cluster]->animationObject->maxAnimationI = value;
         }
         request->send(200, "application/json", "{}");
     });
@@ -151,14 +191,97 @@ void setupServer() {
         clusters[cluster]->changeAnimation(value);
         request->send(200, "application/json", "{}");
     });
+
+    server.on("/api/create_cluster", HTTP_POST, [](AsyncWebServerRequest *request) {
+        StaticJsonDocument<200> doc;
+        DeserializationError error = deserializeJson(doc, request->getHeader("data")->value().c_str());
+        Serial.println(request->getHeader("data")->value().c_str());
+        if (error) {
+            Serial.print(F("deserializeJson() failed: "));
+            Serial.println(error.f_str());
+            return;
+        }
+
+        int numLights = doc["numLights"];
+        static light *newLights;
+        newLights = (light*) malloc(numLights * sizeof(light));
+
+        for (int i = 0; i < numLights; i++) {
+            int mappedLight = doc["lights"][i];
+            if (occupiedLamps[mappedLight] < 0) {
+                newLights[i] = {mappedLight, 0};
+            }
+        }
+
+        static auto newAnimationObject = new Animations(newLights);
+        static auto newLightCluster = new LightCluster(newLights, numLights, 0, newAnimationObject);
+        clusters[numClusters] = newLightCluster;
+        numClusters++;
+
+        updateOccupiedLamps();
+
+        request->send(200, "application/json", "{}");
+    });
+
+    server.on("/api/delete_cluster", HTTP_POST, [](AsyncWebServerRequest *request) {
+        StaticJsonDocument<200> doc;
+        DeserializationError error = deserializeJson(doc, request->getHeader("data")->value().c_str());
+        Serial.println(request->getHeader("data")->value().c_str());
+        if (error) {
+            Serial.print(F("deserializeJson() failed: "));
+            Serial.println(error.f_str());
+            return;
+        }
+
+        int targetCluster = doc["cluster"];
+
+        for (int i = 0; i < numClusters; i++) {
+            if (i == targetCluster) {
+                delete[]clusters[i];
+            }
+            if (i > targetCluster) {
+                clusters[i-1] = clusters[i];
+            }
+        }
+        numClusters--;
+
+        updateOccupiedLamps();
+
+        request->send(200, "application/json", "{}");
+    });
+
+    server.on("/api/sync", HTTP_POST, [](AsyncWebServerRequest *request) {
+        StaticJsonDocument<200> doc;
+        DeserializationError error = deserializeJson(doc, request->getHeader("data")->value().c_str());
+        Serial.println(request->getHeader("data")->value().c_str());
+        if (error) {
+            Serial.print(F("deserializeJson() failed: "));
+            Serial.println(error.f_str());
+            return;
+        }
+
+        for (int i = 0; i < numClusters; i++) {
+            clusters[i]->animationObject->animationI = 0;
+        }
+        request->send(200, "application/json", "{}");
+    });
 }
 
 void setup() {
     // write your initialization code here
     Serial.begin(115200);
-    clusters[0] = &myCluster;
-    myCluster2.animationObject->delayTimeMS = 10;
-    clusters[1] = &myCluster2;
+
+    static light allLights[NUM_LEDS];
+    for (int i = 0; i < NUM_LEDS; i++) {
+        allLights[i] = {i, 0};
+    }
+
+    static auto startAnimationObject = new Animations(allLights);
+    static auto startCluster = new LightCluster(allLights, NUM_LEDS, 0, startAnimationObject);
+
+    clusters[0] = startCluster;
+    numClusters = 1;
+    updateOccupiedLamps();
 
     Serial.println("\nBooted. Connecting SD card\n");
 
@@ -243,7 +366,10 @@ void loop() {
         }
     }
 
-    bool hasRun = clusters[0]->runAnimation() || clusters[1]->runAnimation();
+    bool hasRun = false;
+    for (int i = 0; i < numClusters; i++) {
+        hasRun = hasRun || clusters[i]->runAnimation();
+    }
     if (hasRun) {
         leds.show();
     }