For project overview, see the main README
These scripts dynamically adjust your Zendure Solarflow 800 Pro power output based on real-time measurements from a Shelly 3EM Pro energy meter. The system automatically balances grid power by adjusting the inverter output to minimize grid import/export.
Three variants are available for different network configurations:
| Script | Connection Method | Used when | Required Variables |
|---|---|---|---|
control_zendure_power_ip.js |
Direct IP/hostname | Device on home WiFi network | HOST, SERIAL |
control_zendure_power_mac.js |
MAC address resolution | Shelly AP mode (range extender) | MAC, SERIAL |
control_zendure_power_find_device.js |
Network scanning | Unknown IP or dynamic networks | SERIAL only |
Use when:
- Zendure device is connected to your home WiFi
- Device has a static IP or predictable hostname
- You want the simplest script
Use when:
- Shelly is in AP mode acting as a WiFi range extender
- Zendure connects directly to Shelly's AP
- IP address changes but MAC remains constant
Use when:
- Device IP is unknown or frequently changes
- Automatic network discovery is needed
- Operating across multiple network interfaces (WiFi AP, WiFi STA, Ethernet)
- Open your Shelly 3EM Pro web interface
- Navigate to Scripts section
- Create a new script and paste the contents of your chosen variant
- Configure the variables at the top of the script (see Configuration section)
- Save and start the script
- Enable "Run on startup" to ensure script runs after device restarts
| Name | Functionality |
|---|---|
| HOST | IP address or hostname of Zendure device (IP variant only) |
| MAC | MAC address of Zendure device (MAC variant only, format: AA:BB:CC:DD:EE:FF) |
| SERIAL | Serial number of Zendure device (required for all variants) |
| MAX_POWER | Maximum power in watts to send to grid (e.g., 800) |
| MAX_POWER_REVERSE | Maximum power in watts to draw from grid (e.g., 1000, negative value internally) |
| REVERSE | Enable charging from grid when excess power available (true/false) |
| REVERSE_STARTUP_POWER | Minimum negative power to start charging from grid (e.g., 30 watts) |
| REVERSE_STOP_POWER | Power threshold to stop charging from grid (e.g., 10 watts) |
| STARTUP_POWER | Minimum power to start inverting to grid (e.g., 30 watts) |
| STOP_POWER | Power threshold to stop inverting (e.g., 15 watts) |
| DEBUG | Enable debug logging (true/false) |
All intervals are defined in seconds.
| Name | Functionality |
|---|---|
| INTERVAL_RUN_MAIN_SCRIPT | Main control loop interval (default: 5, minimum: 5) |
| INTERVAL_RESOLVE_MAC | MAC to IP resolution interval (MAC variant only, default: 300) |
| INTERVAL_SCAN_NETWORK | Network scanning interval (find device variant only, default: 900) |
| INTERVAL_DEVICE_OFFLINE | Timeout before device considered offline (find device variant only, default: 600) |
| CHECK_WIFI_AP | Scan WiFi AP network (find device variant only, true/false) |
| CHECK_WIFI_STA | Scan WiFi STA network (find device variant only, true/false) |
| CHECK_ETH | Scan Ethernet network (find device variant only, true/false) |
Important: Do not set INTERVAL_RUN_MAIN_SCRIPT below 5 seconds. The device needs time to adjust power. More frequent updates cause oscillating values.
- Fetches current device status before setting new limits (avoids unnecessary writes)
- Minimum 5-second interval between power changes
- Concurrency control (only one execution at a time)
- Self-monitoring to detect stuck processes
- Bypass mode detection (recognizes when device is empty or full)
- Reverse charging support (stores excess power from additional inverters)
- MAC to IP resolution for Shelly AP mode (MAC variant)
- Automatic network scanning and device discovery (find device variant)
- Persistent IP storage across restarts (find device variant)
- Power changes under 5 watts are ignored to prevent oscillation
- 5-second minimum interval required between adjustments
- Device must support Zendure local API
Simple home WiFi setup with fixed IP:
let HOST = "192.168.1.100";
let SERIAL = "AB123456789";
let MAX_POWER = 800;
let MAX_POWER_REVERSE = 1000;
let REVERSE = false;
let DEBUG = false;Automatic discovery with grid charging enabled:
let SERIAL = "AB123456789";
let MAX_POWER = 800;
let MAX_POWER_REVERSE = 1000;
let REVERSE = true;
let REVERSE_STARTUP_POWER = 50;
let REVERSE_STOP_POWER = 20;
let STARTUP_POWER = 30;
let STOP_POWER = 15;
let DEBUG = false;
let CHECK_WIFI_AP = true;
let CHECK_WIFI_STA = true;
let CHECK_ETH = false;Shelly as WiFi extender:
let MAC = "AA:BB:CC:DD:EE:FF";
let SERIAL = "AB123456789";
let MAX_POWER = 800;
let INTERVAL_RESOLVE_MAC = 300; // Resolve every 5 minutes
let DEBUG = false;Use the watchdog script to monitor this script and automatically restart if it crashes. See shelly_script_checks/README.md for details.