from machine import Pin, ADC, I2C
import time
import network
import ubinascii
from umqtt.simple import MQTTClient
from pico_i2c_lcd import I2cLcd

# Konfigurasi WiFi
WIFI_SSID = 'Wokwi-GUEST'
WIFI_PASS = ''

# Konfigurasi MQTT
MQTT_BROKER = "broker.hivemq.com"
MQTT_CLIENT_ID = ubinascii.hexlify(machine.unique_id()).decode()  # ID unik untuk setiap perangkat
MQTT_TOPIC_PUBLISH = "hydroponics/data"  # Topik untuk mempublikasikan data
MQTT_TOPIC_CONTROL = "hydroponics/control"  # Topik untuk menerima kontrol

# Inisialisasi WiFi
wifi = network.WLAN(network.STA_IF)
if not wifi.isconnected():
    print("Connecting to WiFi...")
    wifi.active(True)
    wifi.connect(WIFI_SSID, WIFI_PASS)
    while not wifi.isconnected():
        print(".", end="")
        time.sleep(1)
print('\nConnected to WiFi, IP:', wifi.ifconfig()[0])

# Inisialisasi MQTT
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER)

def mqtt_connect():
    try:
        client.connect()
        print("Connected to MQTT Broker")
    except Exception as e:
        print("Failed to connect to MQTT Broker:", e)
        time.sleep(5)
        machine.reset()

def mqtt_callback(topic, msg):
    print(f"Received message on {topic}: {msg}")
    # Logika kontrol berdasarkan pesan dari topik "hydroponics/control"
    if topic == MQTT_TOPIC_CONTROL.encode():
        control_data = msg.decode().split(",")
        ph_up = int(control_data[0])
        ph_down = int(control_data[1])
        nutrisi = int(control_data[2])

        relay_ph_up.value(ph_up)
        relay_ph_down.value(ph_down)
        relay_nutrisi.value(nutrisi)

client.set_callback(mqtt_callback)
mqtt_connect()
client.subscribe(MQTT_TOPIC_CONTROL)

# Inisialisasi sensor dan aktuator
ph_sensor = ADC(26)  # Sensor pH
tds_sensor = ADC(27)  # Sensor TDS

relay_ph_up = Pin(15, Pin.OUT)
relay_ph_down = Pin(16, Pin.OUT)
relay_nutrisi = Pin(17, Pin.OUT)

i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
lcd = I2cLcd(i2c, 0x27, 2, 16)

# Rentang pH dan TDS
PH_MIN, PH_MAX = 6.0, 7.0
TDS_MIN, TDS_MAX = 1260, 1610

# Fungsi pembacaan sensor
def read_ph():
    return round((ph_sensor.read_u16() / 65535) * 14, 2)

def read_tds():
    return int((tds_sensor.read_u16() / 65535) * 2000)

# Fungsi kontrol dan indikator LED
def control_and_update():
    ph = read_ph()
    tds = read_tds()

    # Kontrol pH
    if ph < PH_MIN:
        relay_ph_up.value(1)
        relay_ph_down.value(0)
    elif ph > PH_MAX:
        relay_ph_up.value(0)
        relay_ph_down.value(1)
    else:
        relay_ph_up.value(0)
        relay_ph_down.value(0)

    # Kontrol TDS
    if tds < TDS_MIN:
        relay_nutrisi.value(1)
    else:
        relay_nutrisi.value(0)

    # Tampilkan di LCD
    lcd.clear()
    lcd.putstr(f"pH: {ph}\nTDS: {tds} ppm")
    print(f"pH: {ph}, TDS: {tds} ppm")

# Fungsi untuk mengirim data sensor ke MQTT
def upload_data():
    ph = read_ph()
    tds = read_tds()
    payload = f"{ph},{tds}"
    try:
        client.publish(MQTT_TOPIC_PUBLISH, payload)
        print(f"Published: {payload}")
    except Exception as e:
        print("Failed to publish data:", e)

# Loop utama
while True:
    try:
        client.check_msg()  # Periksa pesan MQTT masuk
        control_and_update()
        upload_data()
        time.sleep(5)
    except Exception as e:
        print("Error:", e)
        mqtt_connect()