Chewpacker

Multi-threaded Web Server

Jan 11th, 2021 (edited)
417
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.12 KB | None | 0 0
  1. #include <iostream>
  2. #include <chrono>
  3. #include <string>
  4. #include <atomic>
  5. #include <stdlib.h>
  6. #include <WiFi.h>
  7. #include <FastLED.h>
  8.  
  9. #define NUM_LEDS 300
  10. #define DATA_PIN 5
  11. #define LED_TYPE WS2812B
  12. #define COLOUR_ORDER GRB
  13. #define BRIGHTNESS 64
  14.  
  15. int j = NUM_LEDS-1;
  16. int CHECK = 0;
  17. int Q = NUM_LEDS/4;
  18. int H = NUM_LEDS/2;
  19. int T = 3*Q;
  20. CRGB leds[NUM_LEDS];
  21.  
  22. const char* ssid     = "TheDnBCave";
  23. const char* password = "**************";
  24.  
  25. WiFiServer server(80);
  26.  
  27. String redString = "0";
  28. String greenString = "0";
  29. String blueString = "0";
  30. String intensityString = "0";
  31. String checkString = "0";
  32. int pos1 = 0;
  33. int pos2 = 0;
  34. int pos3 = 0;
  35. int pos4 = 0;
  36. int pos5 = 0;
  37.  
  38. String header;
  39. std::atomic_int R(0);
  40. std::atomic_int G(0);
  41. std::atomic_int B(0);
  42. std::atomic_int I(0);
  43. std::atomic_int C(0);
  44.  
  45. int r_holder;
  46. int g_holder;
  47. int b_holder;
  48. int i_holder;
  49. int c_holder;
  50.  
  51. std::atomic_int Ri(0);
  52. std::atomic_int Gi(0);
  53. std::atomic_int Bi(0);
  54. std::atomic_int Ii(0);
  55. std::atomic_int Ci(0);
  56.  
  57. TaskHandle_t Disp;
  58. TaskHandle_t Serv;
  59.  
  60. // Setting PWM frequency, channels and bit resolution
  61. const int freq = 5000;
  62. const int dataChannel = 0;
  63. // Bit resolution 2^8 = 256
  64. const int resolution = 8;
  65.  
  66. // Current time
  67. unsigned long currentTime = millis();
  68. // Previous time
  69. unsigned long previousTime = 0;
  70. // Define timeout time in milliseconds (example: 2000ms = 2s)
  71. const long timeoutTime = 2000;
  72.  
  73. void setup() {
  74.   FastLED.addLeds<LED_TYPE, DATA_PIN, COLOUR_ORDER>(leds, NUM_LEDS);
  75.   FastLED.setBrightness(BRIGHTNESS);
  76.  
  77.   Serial.begin(115200);
  78.  
  79.   // configure LED PWM functionalitites
  80.   ledcSetup(dataChannel, freq, resolution);
  81.  
  82.   // attach the channel to the GPIO to be controlled
  83.   ledcAttachPin(DATA_PIN, dataChannel);
  84.  
  85.   // Connect to Wi-Fi network with SSID and password
  86.   Serial.print("Connecting to ");
  87.   Serial.println(ssid);
  88.   WiFi.begin(ssid, password);
  89.   while (WiFi.status() != WL_CONNECTED) {
  90.     delay(500);
  91.     Serial.print(".");
  92.   }
  93.   // Print local IP address and start web server
  94.   Serial.println("");
  95.   Serial.println("WiFi connected.");
  96.   Serial.println("IP address: ");
  97.   Serial.println(WiFi.localIP());
  98.   server.begin();
  99.  
  100.   xTaskCreatePinnedToCore(
  101.       Display, /* Function to implement the task */
  102.       "Display", /* Name of the task */
  103.       10000,  /* Stack size in words */
  104.       NULL,  /* Task input parameter */
  105.       1,  /* Priority of the task */
  106.       &Disp,  /* Task handle. */
  107.       1); /* Core where the task should run */
  108.  
  109.    xTaskCreatePinnedToCore(
  110.       Server, /* Function to implement the task */
  111.       "Server", /* Name of the task */
  112.       10000,  /* Stack size in words */
  113.       NULL,  /* Task input parameter */
  114.       0,  /* Priority of the task */
  115.       &Serv,  /* Task handle. */
  116.       0); /* Core where the task should run */
  117. }
  118.  
  119.  
  120. bool hasChanged(){
  121.   if(R.load(std::memory_order_acquire) != Ri.load(std::memory_order_acquire)
  122.   || G.load(std::memory_order_acquire) != Gi.load(std::memory_order_acquire)
  123.   || B.load(std::memory_order_acquire) != Bi.load(std::memory_order_acquire)
  124.   || I.load(std::memory_order_acquire) != Ii.load(std::memory_order_acquire)
  125.   || C.load(std::memory_order_acquire) != Ci.load(std::memory_order_acquire))
  126.   {
  127.         Ri.store(R.load(std::memory_order_acquire), std::memory_order_release);
  128.         Gi.store(G.load(std::memory_order_acquire), std::memory_order_release);
  129.         Bi.store(B.load(std::memory_order_acquire), std::memory_order_release);
  130.         Ii.store(I.load(std::memory_order_acquire), std::memory_order_release);
  131.         Ci.store(C.load(std::memory_order_acquire), std::memory_order_release);
  132.         return true;
  133.   }
  134.   else{
  135.     return false;
  136.     }
  137. }
  138. void Server(void * pvParameters){
  139. for(;;){
  140.   WiFiClient client = server.available();   // Listen for incoming clients
  141.  
  142.   if (client) {                             // If a new client connects,
  143.     currentTime = millis();
  144.     previousTime = currentTime;
  145.     Serial.println("New Client.");          // print a message out in the serial port
  146.     String currentLine = "";                // make a String to hold incoming data from the client
  147.     while (client.connected() && currentTime - previousTime <= timeoutTime) {            // loop while the client's connected
  148.       currentTime = millis();
  149.       if (client.available()) {             // if there's bytes to read from the client,
  150.         char c = client.read();             // read a byte, then
  151.         Serial.write(c);                    // print it out the serial monitor
  152.         header += c;
  153.         if (c == '\n') {                    // if the byte is a newline character
  154.           // if the current line is blank, you got two newline characters in a row.
  155.           // that's the end of the client HTTP request, so send a response:
  156.           if (currentLine.length() == 0) {
  157.             // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
  158.             // and a content-type so the client knows what's coming, then a blank line:
  159.             client.println("HTTP/1.1 200 OK");
  160.             client.println("Content-type:text/html");
  161.             client.println("Connection: close");
  162.             client.println();
  163.                    
  164.             // Display the HTML web page
  165.             client.println("<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width =device-width, initial-scale=1\"><link rel=\"icon\" href=\"data:,\"><link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\"></head><body><div class=\"container\"><div class=\"row\"><h1>ESP Color Picker</h1></div><a class=\"btn btn-primary btn-lg\" href=\"#\" id=\"change_color\" role=\"button\">Change Color</a><input id=\"rgb\" type=\"text\" value=\"7F7F7F\" style=\"background:#7f7f7f\"><div><input id=\"r\" type=\"range\" min=\"0\" max=\"255\" onchange=\"updateColour()\"/><label for=\"r\">Red</label><input id=\"g\" type=\"range\" min=\"0\" max=\"255\" onchange=\"updateColour()\" /><label for=\"g\">Green</label><input id=\"b\" type=\"range\" min=\"0\" max=\"255\" onchange=\"updateColour()\" /><label for=\"b\">Blue</label><input id=\"i\" type=\"range\" min=\"0\" max=\"64\" onchange=\"updateColour()\" /><label for=\"i\">Intensity</label></div><div><a class=\"btn btn-primary btn-lg\" href=\"#\" id=\"change_mode\" role=\"button\">Change Mode</a><input id=\"r1\" type=\"radio\" name=\"mode-type\" onchange=\"updateMode()\"/><label for=\"r1\">Mode 1</label><input id=\"r2\" type=\"radio\" name=\"mode-type\" onchange=\"updateMode()\"/><label for=\"r2\">Mode 2</label></div><script>function updateColour() {var r = parseInt( document.getElementById(\"r\").value, 10);var g = parseInt( document.getElementById(\"g\").value, 10);var b = parseInt(document.getElementById(\"b\").value, 10); var i = document.getElementById(\"i\").value;var hex = r.toString(16) + g.toString(16) + b.toString(16);document.getElementById('rgb').value = hex;document.getElementById('rgb').style.background = \"#\" + hex;document.getElementById(\"change_color\").href = \"?r\" + r + \"g\" + g + \"b\" + b + \"i\" + i + \"&\";}function updateMode(){var r;if(document.getElementById('r1').checked){r = 1}else if(document.getElementById('r2').checked){r = 2;}document.getElementById(\"change_mode\").href = \"?m\"+ r + \"&\";}</script></body></html>");
  166.  
  167.             // The HTTP response ends with another blank line
  168.             client.println();
  169.  
  170.             // Request sample: /?r201g32b255&
  171.             // Red = 201 | Green = 32 | Blue = 255
  172.             if(header.indexOf("GET /?r") >= 0) {
  173.               Serial.println("Static colour selected - calculating RGB Values...");
  174.               pos1 = header.indexOf('r');
  175.               pos2 = header.indexOf('g');
  176.               pos3 = header.indexOf('b');
  177.               pos4 = header.indexOf('i');
  178.               pos4 = header.indexOf('&');
  179.               redString = header.substring(pos1+1, pos2);
  180.               greenString = header.substring(pos2+1, pos3);
  181.               blueString = header.substring(pos3+1, pos4);
  182.               intensityString = header.substring(pos4+1, pos5);
  183.               R.store(redString.toInt(), std::memory_order_release);
  184.               G.store(greenString.toInt(), std::memory_order_release);
  185.               B.store(blueString.toInt(), std::memory_order_release);
  186.               I.store(intensityString.toInt(), std::memory_order_release);
  187.               FastLED.setBrightness(intensityString.toInt());
  188.  
  189.               Serial.println(R.load(std::memory_order_acquire));
  190.               Serial.println(G.load(std::memory_order_acquire));
  191.               Serial.println(B.load(std::memory_order_acquire));
  192.             }
  193.  
  194.             else if(header.indexOf("GET /?m") >= 0) {
  195.               Serial.println("Looping mode selected - calculating mode selection...");
  196.               pos1 = header.indexOf('m');
  197.               pos2 = header.indexOf('&');
  198.               checkString = header.substring(pos1+1, pos2);
  199.               C.store(checkString.toInt(), std::memory_order_release);
  200.  
  201.               Serial.println(C.load(std::memory_order_acquire));
  202.             }
  203.             // Break out of the while loop
  204.             break;
  205.           } else { // if you got a newline, then clear currentLine
  206.             currentLine = "";
  207.           }
  208.         } else if (c != '\r') {  // if you got anything else but a carriage return character,
  209.           currentLine += c;      // add it to the end of the currentLine
  210.         }
  211.       }
  212.     }
  213.     // Clear the header variable
  214.     header = "";
  215.     // Close the connection
  216.     client.stop();
  217.     Serial.println("Client disconnected.");
  218.     Serial.println("");
  219.     vTaskDelay(50);
  220.   }
  221. }
  222. }
  223.  
  224. void Display(void * pvParameters){
  225.   for (;;){
  226.     if (hasChanged())
  227.     {
  228.       Serial.println("Change detected!");
  229.       c_holder = C.load(std::memory_order_acquire);
  230.  
  231.   if(c_holder == 0)
  232.   {
  233.     Serial.println("I am in the static display block");
  234.     r_holder = R.load(std::memory_order_acquire);
  235.     g_holder = G.load(std::memory_order_acquire);
  236.     b_holder = B.load(std::memory_order_acquire);
  237.     i_holder = I.load(std::memory_order_acquire);
  238.  
  239.  
  240.     Serial.println("Now updating all elements with the following values: ");
  241.     Serial.println(r_holder);
  242.     Serial.println(g_holder);
  243.     Serial.println(b_holder);
  244.    
  245.     //for(int i=0; i<NUM_LEDS/2; i++)
  246.     for (int i=0; i<NUM_LEDS; i++)
  247.               {
  248.                  leds[i].setRGB(r_holder, g_holder, b_holder);
  249.                  Serial.print("[");
  250.                  Serial.print(i);
  251.                  Serial.print("].R = ");
  252.                  Serial.println(leds[i].r);
  253.               }
  254.               Serial.println("All elements updated - showing");
  255.               FastLED.show();
  256.               //j=NUM_LEDS-1;
  257.   }
  258.   else if(c_holder == 1)
  259.   {
  260.     Serial.println("I am in mode 1");
  261.                       for(int i=0; i<50; i++)
  262.                       {
  263.                           if(i==49)
  264.                           {
  265.                               for(int j=49; j>=0; j--)
  266.                               {
  267.                                   leds[j] = CRGB::Red;
  268.                                   leds[j+50] = CRGB::Orange;
  269.                                   leds[j+100] = CRGB::Yellow;
  270.                                   leds[j+150] = CRGB::Green;
  271.                                   leds[j+200] = CRGB::Blue;
  272.                                   leds[j+250] = CRGB::Purple;
  273.                                   FastLED.show();
  274.                                   leds[j] = CRGB::Black;
  275.                                   leds[j+50] = CRGB::Black;
  276.                                   leds[j+100] = CRGB::Black;  
  277.                                   leds[j+150] = CRGB::Black;
  278.                                   leds[j+200] = CRGB::Black;
  279.                                   leds[j+250] = CRGB::Black;
  280.                  
  281.                               }  
  282.                           }
  283.                           else
  284.                           {
  285.                               leds[i] = CRGB::Red;
  286.                               leds[i+50] = CRGB::Orange;
  287.                               leds[i+100] = CRGB::Yellow;
  288.                               leds[i+150] = CRGB::Green;
  289.                               leds[i+200] = CRGB::Blue;
  290.                               leds[i+250] = CRGB::Purple;
  291.                               FastLED.show();
  292.                           }          
  293.                       }
  294.                   }
  295.  else if(c_holder == 2)
  296.                   {
  297.                     Serial.println("I am in mode 2");
  298.                       for(int i=0; i<NUM_LEDS; i++)
  299.                       {
  300.                           leds[i] = CRGB::Red;
  301.                           leds[(i+Q) % NUM_LEDS] = CRGB::Green;
  302.                           leds[(i+H) % NUM_LEDS] = CRGB::Blue;
  303.                           leds[(i+T) % NUM_LEDS] = CRGB::Yellow;
  304.  
  305.                            FastLED.show();
  306.                            delay(20);
  307.  
  308.                            for(int i=0; i<NUM_LEDS; i++)
  309.                            {
  310.                               leds[i] = CRGB::Black;
  311.                            }
  312.                       }
  313.                  
  314.                    }
  315.     }
  316.     vTaskDelay(50);
  317.   }
  318. }
  319.  
  320. void loop() {
  321.  vTaskDelay(50);
  322. }
Advertisement
Add Comment
Please, Sign In to add comment