The problem
I have a Pergolux bioclimatic pergola with motorized slats. It’s one of those pergolas with adjustable louvers that open and close to manage sun and rain. The motor is controlled by a 433MHz remote — model PX140-D&C, made by A-OK Technology. No app. No API. No home automation integration. Just a remote with four buttons.
The problem is wind. When a strong gust hits with the slats open, they rattle and take mechanical stress. Ideally, a system would monitor the weather and automatically close the slats when wind exceeds a certain threshold. But Pergolux offers nothing of the sort — the system is designed to be manual.
So I decided to build one myself.
Automated wind protection system for Pergolux bioclimatic pergola using 433.92 MHz RF communication. — first commit, February 6
The shopping list
The bill of materials was surprisingly short:
- ESP32 DevKit v1 — microcontroller with built-in WiFi, the brain of the system
- CC1101 E07-M1101D-SMA V2.0 — 433MHz radio module with SMA antenna, to speak the same language as the remote
- Breadboard and jumper wires — for prototyping
Total cost: about 15-20 euros. The beauty of open source hardware.
The hardware
The connection is standard SPI between ESP32 and CC1101: seven wires between the two modules. VCC, GND, then MOSI, MISO, SCK, CSN and GDO0 — the pin the ESP32 uses to directly control radio transmission.
Brownout detector disabled for stable WiFi init. Serial flush on boot to prevent garbage command execution. monitor_dtr/rts disabled to prevent ESP32 reset on monitor connect. — from the web server commit
Three lines that tell the story of hours of hardware debugging. The ESP32’s brownout detector triggered during WiFi init. The serial port executed garbage commands at boot. The monitor reset the board on every connection. Problems no tutorial mentions.

Reverse engineering the RF protocol
This was the most interesting part. The Pergolux remote uses the proprietary A-OK protocol: 65-bit frames with OOK/ASK modulation, an AGC preamble, and no rolling code. Each transmission consists of 8 repetitions of the same frame, for a total duration of about 520 milliseconds.
Reverse-engineered the Pergolux S2 remote protocol (A-OK Technology, 65-bit OOK/ASK at 433.92MHz). Implemented reusable AOK library for CC1101-based transmission with pairing and multi-channel control. — February 11
The encoding is tri-state: each bit is represented by two pulses of different duration — 270 microseconds and 565 microseconds, alternating depending on whether the bit is 0 or 1. The frame contains a fixed remote ID (24 bits), a channel address (16 bits), the command (8 bits) and a checksum.
The process was iterative. First, signal capture with the CC1101 in receive mode, then pattern analysis with Python scripts — from OOK vs FSK comparison (the breakthrough: RSSI -29dBm vs -77dBm, OOK confirmed), to timing capture via interrupts. Then protocol identification through FCC reports and a GitHub repository documenting the A-OK standard.
Includes protocol documentation, wiring diagram, and analysis scripts from the sniffing phase. — same commit
An important detail: the “8 pulses” initially captured were just the AGC preamble, not the actual data. The CC1101 in demodulation mode at 4.8kbps was filtering out the data bits. It took several iterations of Python scripts (from v10 to v16) to figure that out.
The software
Once the RF protocol was working, I built the complete system in five days — from web server to automatic protection.
Web UI with controls for lamelle (close/open/stop) and LED. Real-time weather data from Open-Meteo. Auto-protection: closes lamelle on wind >=40 km/h or rain >0.5mm, reopens when wind <25 km/h and rain =0mm (hysteresis to prevent bouncing). — February 12
A web server for manual control. Connection to Open-Meteo weather APIs to monitor wind, gusts and rain every five minutes. An automatic protection system with hysteresis — the key detail: different thresholds for closing (40 km/h) and reopening (25 km/h) to prevent the slats from constantly opening and closing in variable wind.
UPnP opens port 8080 on router mapped to internal port 80. DuckDNS updates public IP every 5 minutes. HTTP basic auth protects all endpoints. — same day
DuckDNS for remote access, Telegram notifications to know what the system is doing, and OTA updates so I don’t have to disassemble the ESP32 every time I modify the firmware. All in one day.
35 unit tests covering manual/auto actions, hysteresis, cooldown and real-world scenarios. — February 12
35 unit tests from day one. Not out of discipline, but out of necessity: the protection system has too many edge cases to be tested only on the real pergola.
The debugging
Debugging was the most educational part — and the most frustrating.
RF commands from HTTP handlers were unreliable due to WiFi/TCP interrupt activity disrupting the precise OOK timing (270/565us pulses). Now all RF transmissions execute in the main loop context via a pendingCmd queue. — February 12
The central problem: OOK signals require microsecond-precise timing — 270us and 565us per bit. But when the web server handles an HTTP request, WiFi/TCP interrupts disrupt the RF transmission and corrupt the signal. The solution was to move all RF commands to a queue and execute them in the main loop, where there are no network interrupts.
Also defers sendTelegram() via pendingTelegram buffer to prevent blocking the web server for 2-5 seconds during HTTPS POST. — same commit
Telegram was blocking too: an HTTPS POST to Telegram’s servers took 2-5 seconds, during which the web server was unresponsive. Solution: async buffer.

Collaborating with an AI
Every commit in this project carries the signature Co-Authored-By: Claude Opus 4.6. It’s not a courtesy credit — it’s the reality of how this was built.
Not in the sense that the AI wrote the code and I copied it. In the sense that I had the problem, the physical pergola, the domain understanding — and Claude had the technical patterns, the libraries, the knowledge of RF protocols and embedded architecture.
The result was being able to tackle a completely new domain for me — embedded systems, radio protocols, microcontroller firmware — in a weekend. Twenty years of software experience, but I had never touched an ESP32 before this project. AI bridged the gap between “I can code” and “I can code this”.
It’s not that the AI did the hard work. The hard work was understanding why stop wasn’t working, isolating the blocking I/O problem, designing the protection system architecture. AI accelerated everything else — the boilerplate, PlatformIO syntax, Open-Meteo APIs, CC1101 configuration.
Reflection
AI is giving us opportunities we wouldn’t have had before. I’m not just talking about speed — I’m talking about accessibility. Domains that would have required weeks of study are now reachable in days. It’s a new way to frame problems, to reason about feasibility, to explore unknown territory with a safety net.
But every time I close a session with Claude, I’m left with an ambivalent feeling. Yes, I built something that works. Yes, I learned. But did I learn as much as I would have without the AI? Did I truly understand the OOK protocol timing, or did I just verify that the generated code worked?
The project was satisfying precisely because it required real understanding — not just prompts. But the line is thinning. And I wonder: in a world where AI can bridge any knowledge gap in real time, how important is it to maintain the ability to focus and think deeply?