import network
import urequests
import machine
import utime
import json
import os
import math
from machine import Pin, ADC
from dht import DHT22
# WiFi Configuration
SSID = "Wokwi-GUEST"
PASSWORD = ""
OPENWEATHER_API_KEY = "your_openweather_api_key"
LOCATION = "Messe Nord Icc"
OPENWEATHER_URL = f"http://api.openweathermap.org/data/2.5/weather?q={LOCATION}&appid={OPENWEATHER_API_KEY}&units=metric"
# Sensor Pins Configuration
DHT22_PIN = 15 # GPIO for DHT22
SOIL_MOISTURE_PIN = 20 # ADC GPIO for soil moisture sensor
RELAY_PIN = 2 # GPIO for relay controlling solenoid valve
# Hardware Setup
dht_sensor = DHT22(Pin(DHT22_PIN))
soil_sensor = ADC(Pin(SOIL_MOISTURE_PIN))
relay = Pin(RELAY_PIN, Pin.OUT)
DATA_FILE = "sensor_data.json"
MODEL_FILE = "rf_model.json"
# WiFi Connection
def connect_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while not wlan.isconnected():
pass
print("Connected to WiFi")
# Fetch Weather Data
def get_weather():
try:
response = urequests.get(OPENWEATHER_URL)
weather_data = response.json()
response.close()
return weather_data["main"]["temp"], weather_data["main"]["humidity"], weather_data["weather"][0]["main"]
except:
return None, None, None
# Read Sensors
def read_sensors():
dht_sensor.measure()
temp = dht_sensor.temperature()
humidity = dht_sensor.humidity()
soil_moisture = soil_sensor.read()
return temp, humidity, soil_moisture
# Simple Random Forest Classifier
class SimpleRandomForest:
def __init__(self, model_file=MODEL_FILE):
self.model_file = model_file
self.trees = []
self.load_model()
def load_model(self):
if os.path.exists(self.model_file):
with open(self.model_file, "r") as f:
self.trees = json.load(f)
else:
self.trees = []
def predict(self, features):
if not self.trees:
return 1 if features[2] < 500 else 0 # Default logic
votes = []
for tree in self.trees:
vote = tree["threshold"] < features[tree["feature"]]
votes.append(int(vote))
return round(sum(votes) / len(votes))
def train_and_save(self, X, y):
self.trees = []
for i in range(5): # Simulate 5 decision trees
feature = i % 3 # Cycle through features
threshold = sum(x[feature] for x in X) / len(X) if X else 500
self.trees.append({"feature": feature, "threshold": threshold})
with open(self.model_file, "w") as f:
json.dump(self.trees, f)
# Collect Data
def collect_data(temp, humidity, soil_moisture, weather, decision):
if os.path.exists(DATA_FILE):
with open(DATA_FILE, "r") as f:
data = json.load(f)
else:
data = {"X": [], "y": []}
data["X"].append([temp, humidity, soil_moisture])
data["y"].append(decision)
with open(DATA_FILE, "w") as f:
json.dump(data, f)
if len(data["X"]) >= 2160: # 15 days of data (10 min intervals -> 144 per day)
print("Training new model...")
model = SimpleRandomForest()
model.train_and_save(data["X"], data["y"])
# Main Logic
def main():
connect_wifi()
model = SimpleRandomForest()
while True:
temp, humidity, soil_moisture = read_sensors()
weather_temp, weather_humidity, weather = get_weather()
if weather_temp is not None:
features = [weather_temp, weather_humidity, soil_moisture]
prediction = model.predict(features)
if prediction == 1:
relay.value(1) # Activate solenoid
print("Watering plants...")
utime.sleep(5) # Keep solenoid open for 5 seconds
relay.value(0) # Close solenoid
print("Watering complete")
else:
print("Waiting for rain...")
collect_data(weather_temp, weather_humidity, soil_moisture, weather, prediction)
else:
print("Failed to retrieve weather data")
utime.sleep(600) # Check every 10 minutes
if __name__ == "__main__":
main()