-
Notifications
You must be signed in to change notification settings - Fork 0
Trying to fix the high CPU uses #8
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| from GpioManager import GpioManager | ||
| import time | ||
| import os | ||
| from datetime import datetime | ||
|
|
||
| from PinDescription import * | ||
|
|
@@ -64,6 +65,7 @@ def isNightTime(): | |
| def main(): | ||
| gpio = GpioManager() | ||
| setupGpio(gpio) | ||
| lastDistance = readDistance(gpio, ULTRASONIC_TRIG, ULTRASONIC_ECHO) | ||
|
|
||
| # Default valves and durations | ||
| valve1Duration = VALVE1_DEFAULT_DURATION | ||
|
|
@@ -83,10 +85,19 @@ def main(): | |
|
|
||
| try: | ||
| lastCheckTime = time.time() | ||
| lastRtDbCheck = time.time() | ||
| preNightFillActive = False | ||
| preNightFillStartTime = None | ||
|
|
||
| # File modification tracking for efficient change detection | ||
| lastRtDbModTime = 0 | ||
| rtDb = readRtDb() # Initial read | ||
| try: | ||
| lastRtDbModTime = os.path.getmtime(RT_DB_FILE) | ||
| except OSError: | ||
| pass | ||
|
|
||
| while True: | ||
| print("Main loop iteration...") | ||
| currentTime = time.time() | ||
| now = datetime.now() | ||
|
|
||
|
|
@@ -97,47 +108,73 @@ def main(): | |
| aftrn5RunDone = False | ||
| lastDay = now.day | ||
|
|
||
| rtDb = readRtDb() | ||
| configUpdateAvailable = rtDb.get("configUpdateAvailable", False) | ||
| # Efficient database change detection using file modification time | ||
| configUpdateAvailable = False | ||
| needsDbRead = False | ||
|
|
||
| # Check if file has been modified (lightweight operation) | ||
| try: | ||
| currentModTime = os.path.getmtime(RT_DB_FILE) | ||
| if currentModTime != lastRtDbModTime: | ||
| print("Database Updated - Reading immediately") | ||
| needsDbRead = True | ||
| lastRtDbModTime = currentModTime | ||
| elif currentTime - lastRtDbCheck >= DB_CHECK_INTERVAL: | ||
| # Periodic check even if file hasn't changed (for safety) | ||
| needsDbRead = True | ||
| except OSError: | ||
| # File doesn't exist or can't be accessed, try periodic read | ||
| if currentTime - lastRtDbCheck >= DB_CHECK_INTERVAL: | ||
| needsDbRead = True | ||
|
|
||
| if needsDbRead: | ||
| rtDb = readRtDb() | ||
| configUpdateAvailable = rtDb.get("configUpdateAvailable", False) | ||
| lastRtDbCheck = currentTime | ||
| if configUpdateAvailable: | ||
| print("Processing config update from web interface") | ||
| # If no read needed, use cached rtDb (already initialized above) | ||
|
|
||
| # Check for config updates for valves | ||
| if configUpdateAvailable: | ||
| valve1Duration = rtDb.get("valve1Duration", VALVE1_DEFAULT_DURATION) | ||
| valve2Duration = rtDb.get("valve2Duration", VALVE2_DEFAULT_DURATION) | ||
| print(f"Updated valve durations: Valve1={valve1Duration} min, Valve2={valve2Duration} min") | ||
|
|
||
| # Morning valve operation | ||
| if now.hour == MORNING_8AM and not morning8RunDone: | ||
| print("Morning run: Activating valves.") | ||
| gpio.output(VALVE1_PIN, True) | ||
| gpio.output(VALVE2_PIN, True) | ||
| valve1On = True | ||
| valve2On = True | ||
| valve1StartTime = currentTime | ||
| valve2StartTime = currentTime | ||
| morning8RunDone = True | ||
|
|
||
| # Afternoon valve operation | ||
| if now.hour == AFTERNOON_5PM and not aftrn5RunDone: | ||
| print("Afternoon run: Activating valves.") | ||
| gpio.output(VALVE1_PIN, True) | ||
| gpio.output(VALVE2_PIN, True) | ||
| valve1On = True | ||
| valve2On = True | ||
| valve1StartTime = currentTime | ||
| valve2StartTime = currentTime | ||
| aftrn5RunDone = True | ||
|
|
||
| # Evening valve operation | ||
| if now.hour == NIGHT_9PM and not evening9RunDone: | ||
| print("Evening run: Activating valves.") | ||
| gpio.output(VALVE1_PIN, True) | ||
| gpio.output(VALVE2_PIN, True) | ||
| valve1On = True | ||
| valve2On = True | ||
| valve1StartTime = currentTime | ||
| valve2StartTime = currentTime | ||
| evening9RunDone = True | ||
| print(f"Updated valve durations: Valve1 = {valve1Duration} min, Valve2 = {valve2Duration} min") | ||
|
|
||
| # Only check for scheduled valve operations once per minute to reduce processing | ||
| if now.second == 0: # Only check at the beginning of each minute | ||
| # Morning valve operation | ||
| if now.hour == MORNING_8AM and not morning8RunDone: | ||
| print("Morning run: Activating valves.") | ||
| gpio.output(VALVE1_PIN, True) | ||
| gpio.output(VALVE2_PIN, True) | ||
| valve1On = True | ||
| valve2On = True | ||
| valve1StartTime = currentTime | ||
| valve2StartTime = currentTime | ||
| morning8RunDone = True | ||
|
|
||
| # Afternoon valve operation | ||
| if now.hour == AFTERNOON_5PM and not aftrn5RunDone: | ||
| print("Afternoon run: Activating valves.") | ||
| gpio.output(VALVE1_PIN, True) | ||
| gpio.output(VALVE2_PIN, True) | ||
| valve1On = True | ||
| valve2On = True | ||
| valve1StartTime = currentTime | ||
| valve2StartTime = currentTime | ||
| aftrn5RunDone = True | ||
|
|
||
| # Evening valve operation | ||
| if now.hour == NIGHT_9PM and not evening9RunDone: | ||
| print("Evening run: Activating valves.") | ||
| gpio.output(VALVE1_PIN, True) | ||
| gpio.output(VALVE2_PIN, True) | ||
| valve1On = True | ||
| valve2On = True | ||
| valve1StartTime = currentTime | ||
| valve2StartTime = currentTime | ||
| evening9RunDone = True | ||
|
|
||
| # Check to turn off valves | ||
| if valve1On and (currentTime - valve1StartTime >= valve1Duration * 60): | ||
|
|
@@ -153,7 +190,13 @@ def main(): | |
| # Original motor logic | ||
| if currentTime - lastCheckTime >= CHECK_INTERVAL_SECONDS: | ||
| distance = readDistance(gpio, ULTRASONIC_TRIG, ULTRASONIC_ECHO) | ||
| print(f"Distance: {distance} cm") | ||
| if distanceIsValid(distance, lastDistance): | ||
| print(f"Distance: {distance} cm") | ||
| lastDistance = distance | ||
| else: | ||
| print(f"Invalid distance reading: {distance} cm; SKIP;") | ||
| time.sleep(0.5) | ||
| continue | ||
| waterLevel = TANK_HEIGHT - distance | ||
| motorStatus = rtDb.get("motorStatus", "OFF") | ||
|
|
||
|
|
@@ -206,7 +249,13 @@ def main(): | |
| lastMotorStatus = motorStatus | ||
| lastWaterLevel = waterLevel | ||
|
|
||
| time.sleep(0.1) # Sleep to reduce CPU usage | ||
| # Smart sleep: shorter sleep when config updates are expected | ||
| if configUpdateAvailable: | ||
| # If we just processed a config update, check again sooner | ||
| time.sleep(0.5) # Quick follow-up check | ||
| else: | ||
| # Normal operation - longer sleep for CPU efficiency | ||
| time.sleep(1) | ||
|
Comment on lines
+252
to
+258
|
||
| except KeyboardInterrupt: | ||
| cleanupGpio(gpio) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,3 +57,13 @@ def ifWaterLevelBelowMin(waterLevel): | |
| return False | ||
| else: | ||
| return False | ||
|
|
||
|
|
||
| def distanceIsValid(distance, lastDistance): | ||
| if distance <= 0: | ||
| return False | ||
| if lastDistance > 0: | ||
| change = abs(distance - lastDistance) | ||
| if change / lastDistance > 0.1: # More than 10% change | ||
|
||
| return False | ||
| return True | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| appVersion: 1.2.2.1005 | ||
| appVersion: 1.2.3.1006 | ||
|
|
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.
This condition may cause valve operations to be missed if the loop iteration doesn't align with second == 0. Consider using a minute-based timestamp comparison instead of relying on the exact second alignment.