- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 111
(wip) AC minor patch cluster #2, and some goodies for 8266 #152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: mdev
Are you sure you want to change the base?
Changes from all commits
ca50bca
              17b648f
              7fbb693
              e2dd1f8
              977d7a4
              8a8e787
              925cc65
              f4b70f4
              98b98b7
              294db38
              dcd1ef4
              23f2a5b
              e286bff
              d86528b
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| #!/bin/bash | ||
| # Some web server stress tests | ||
| # | ||
| # Perform a large number of parallel requests, stress testing the web server | ||
| # TODO: some kind of performance metrics | ||
|  | ||
| # Accepts three command line arguments: | ||
| # - first argument - mandatory - IP or hostname of target server | ||
| # - second argument - target type (optional) | ||
| # - third argument - xfer count (for replicated targets) (optional) | ||
| HOST=$1 | ||
| declare -n TARGET_STR="${2:-JSON_LARGER}_TARGETS" | ||
| REPLICATE_COUNT=$(("${3:-10}")) | ||
|  | ||
| PARALLEL_MAX=${PARALLEL_MAX:-50} | ||
|  | ||
| CURL_ARGS="--compressed --parallel --parallel-immediate --parallel-max ${PARALLEL_MAX}" | ||
| CURL_PRINT_RESPONSE_ARGS="-w %{http_code}\n" | ||
|  | ||
| JSON_TARGETS=('json/state' 'json/info' 'json/si', 'json/palettes' 'json/fxdata' 'settings/s.js?p=2') | ||
| FILE_TARGETS=('' 'iro.js' 'rangetouch.js' 'settings' 'settings/wifi') | ||
| # Replicate one target many times | ||
| function replicate() { | ||
| printf "${1}?%d " $(seq 1 ${REPLICATE_COUNT}) | ||
| } | ||
| read -a JSON_TINY_TARGETS <<< $(replicate "json/nodes") | ||
| read -a JSON_SMALL_TARGETS <<< $(replicate "json/info") | ||
| read -a JSON_LARGE_TARGETS <<< $(replicate "json/si") | ||
| read -a JSON_LARGER_TARGETS <<< $(replicate "json/fxdata") | ||
|  | ||
| # Expand target URLS to full arguments for curl | ||
| TARGETS=(${TARGET_STR[@]}) | ||
| #echo "${TARGETS[@]}" | ||
| FULL_TGT_OPTIONS=$(printf "http://${HOST}/%s -o /dev/null " "${TARGETS[@]}") | ||
| #echo ${FULL_TGT_OPTIONS} | ||
|  | ||
| time curl ${CURL_ARGS} ${FULL_TGT_OPTIONS} | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||||||||||||||||||||||||||||||||||||||
| import numpy as np | ||||||||||||||||||||||||||||||||||||||||||
| import socket | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
| class WledRealtimeClient: | ||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, wled_controller_ip, num_pixels, udp_port=21324, max_pixels_per_packet=126): | ||||||||||||||||||||||||||||||||||||||||||
| self.wled_controller_ip = wled_controller_ip | ||||||||||||||||||||||||||||||||||||||||||
| self.num_pixels = num_pixels | ||||||||||||||||||||||||||||||||||||||||||
| self.udp_port = udp_port | ||||||||||||||||||||||||||||||||||||||||||
| self.max_pixels_per_packet = max_pixels_per_packet | ||||||||||||||||||||||||||||||||||||||||||
| self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||||||||||||||||||||||||||||||||||||||||||
| self._prev_pixels = np.full((3, self.num_pixels), 253, dtype=np.uint8) | ||||||||||||||||||||||||||||||||||||||||||
| self.pixels = np.full((3, self.num_pixels), 1, dtype=np.uint8) | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
| def update(self): | ||||||||||||||||||||||||||||||||||||||||||
| # Truncate values and cast to integer | ||||||||||||||||||||||||||||||||||||||||||
| self.pixels = np.clip(self.pixels, 0, 255).astype(np.uint8) | ||||||||||||||||||||||||||||||||||||||||||
| p = np.copy(self.pixels) | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
| idx = np.where(~np.all(p == self._prev_pixels, axis=0))[0] | ||||||||||||||||||||||||||||||||||||||||||
| num_pixels = len(idx) | ||||||||||||||||||||||||||||||||||||||||||
| n_packets = (num_pixels + self.max_pixels_per_packet - 1) // self.max_pixels_per_packet | ||||||||||||||||||||||||||||||||||||||||||
| idx_split = np.array_split(idx, n_packets) | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
| header = bytes([1, 2]) # WARLS protocol header | ||||||||||||||||||||||||||||||||||||||||||
| for packet_indices in idx_split: | ||||||||||||||||||||||||||||||||||||||||||
| data = bytearray(header) | ||||||||||||||||||||||||||||||||||||||||||
| for i in packet_indices: | ||||||||||||||||||||||||||||||||||||||||||
| data.extend([i, *p[:, i]]) # Index and RGB values | ||||||||||||||||||||||||||||||||||||||||||
| self._sock.sendto(bytes(data), (self.wled_controller_ip, self.udp_port)) | ||||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +21
     to 
      +29
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard zero-changes path; array_split(0) raises When no pixels change, n_packets becomes 0 and np.array_split() throws. -        n_packets = (num_pixels + self.max_pixels_per_packet - 1) // self.max_pixels_per_packet
-        idx_split = np.array_split(idx, n_packets)
+        if num_pixels == 0:
+            return
+        n_packets = (num_pixels + self.max_pixels_per_packet - 1) // self.max_pixels_per_packet
+        idx_split = np.array_split(idx, n_packets)Also consider early-return before building header for the no-change case. 📝 Committable suggestion
 
        Suggested change
       
 🤖 Prompt for AI Agents | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
| self._prev_pixels = np.copy(p) | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||
| ################################## LED blink test ################################## | ||||||||||||||||||||||||||||||||||||||||||
| if __name__ == "__main__": | ||||||||||||||||||||||||||||||||||||||||||
| WLED_CONTROLLER_IP = "192.168.1.153" | ||||||||||||||||||||||||||||||||||||||||||
| NUM_PIXELS = 255 # Amount of LEDs on your strip | ||||||||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||||||||
| wled = WledRealtimeClient(WLED_CONTROLLER_IP, NUM_PIXELS) | ||||||||||||||||||||||||||||||||||||||||||
| print('Starting LED blink test') | ||||||||||||||||||||||||||||||||||||||||||
| while True: | ||||||||||||||||||||||||||||||||||||||||||
| for i in range(NUM_PIXELS): | ||||||||||||||||||||||||||||||||||||||||||
| wled.pixels[1, i] = 255 if wled.pixels[1, i] == 0 else 0 | ||||||||||||||||||||||||||||||||||||||||||
| wled.update() | ||||||||||||||||||||||||||||||||||||||||||
| time.sleep(.01) | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -337,8 +337,6 @@ WLED_GLOBAL int8_t irPin _INIT(IRPIN); | |
| constexpr uint8_t hardwareTX = 1; | ||
| #endif | ||
|  | ||
| //WLED_GLOBAL byte presetToApply _INIT(0); | ||
|  | ||
| WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use | ||
|  | ||
| // WiFi CONFIG (all these can be changed via web UI, no need to set them here) | ||
|  | @@ -374,7 +372,11 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load | |
| //if true, a segment per bus will be created on boot and LED settings save | ||
| //if false, only one segment spanning the total LEDs is created, | ||
| //but not on LED settings save if there is more than one segment currently | ||
| #ifdef WLED_AUTOSEGMENTS | ||
| WLED_GLOBAL bool autoSegments _INIT(true); | ||
| #else | ||
| WLED_GLOBAL bool autoSegments _INIT(false); | ||
| #endif | ||
| WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color | ||
| WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct | ||
| WLED_GLOBAL bool gammaCorrectCol _INIT(true ); // use gamma correction on colors // WLEDMM that's what you would think, but the code tells a different story. | ||
|  | @@ -822,6 +824,10 @@ WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> doc; | |
| #endif // WLEDMM end | ||
| WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0); | ||
|  | ||
| #if defined(ARDUINO_ARCH_ESP32) | ||
| WLED_GLOBAL SemaphoreHandle_t jsonBufferLockMutex _INIT(xSemaphoreCreateRecursiveMutex()); | ||
| #endif | ||
| 
      Comment on lines
    
      +827
     to 
      +829
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential initialization order issue with mutex creation. Creating the recursive mutex with  
 Consider initializing the mutex explicitly in  // Suggested approach 1: Initialize in setup()
#if defined(ARDUINO_ARCH_ESP32)
WLED_GLOBAL SemaphoreHandle_t jsonBufferLockMutex _INIT(NULL);
#endif
// In setup() or initInterfaces():
void WLED::setup() {
  #if defined(ARDUINO_ARCH_ESP32)
  if (jsonBufferLockMutex == NULL) {
    jsonBufferLockMutex = xSemaphoreCreateRecursiveMutex();
  }
  #endif
  // ... rest of setup
}// Suggested approach 2: Lazy initialization with helper
#if defined(ARDUINO_ARCH_ESP32)
WLED_GLOBAL SemaphoreHandle_t jsonBufferLockMutex _INIT(NULL);
inline void ensureJsonMutexInit() {
  if (jsonBufferLockMutex == NULL) {
    jsonBufferLockMutex = xSemaphoreCreateRecursiveMutex();
  }
}
#endif🤖 Prompt for AI AgentsThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the bunny is right here, calling xSemaphoreCreateRecursiveMutex(); before we have entered main() and setup() may or may not work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @softhack007, thanks for confirming! You're absolutely right—calling  The safest fix is to initialize the mutex handle to  In wled00/wled.h (around line 827): #if defined(ARDUINO_ARCH_ESP32)
WLED_GLOBAL SemaphoreHandle_t jsonBufferLockMutex _INIT(NULL);
#endifIn wled00/wled.cpp (in the  void WLED::setup() {
  #if defined(ARDUINO_ARCH_ESP32)
  if (jsonBufferLockMutex == NULL) {
    jsonBufferLockMutex = xSemaphoreCreateRecursiveMutex();
  }
  #endif
  // ... rest of setup code
}This ensures the mutex is created after FreeRTOS is fully initialized and avoids any potential race conditions or initialization failures. You should also add a check in the lock/unlock functions (in  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The things I have learned since I wrote that code! In practice it works: this is because  That said, better practice is to use a pre-allocated  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 
 | ||
|  | ||
| // enable additional debug output | ||
| //WLEDMM: switch between netdebug and serial | ||
| // cannot do this on -S2, due to buggy USBCDC serial driver: canUseSerial | ||
|  | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comma in Bash array splits an element; remove it
This makes 'json/si,' a literal entry.
📝 Committable suggestion
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 20-20: JSON_TARGETS appears unused. Verify use (or export if used externally).
(SC2034)
[warning] 20-20: Use spaces, not commas, to separate array elements.
(SC2054)
🤖 Prompt for AI Agents