import time
import machine
import dht
import json
from umqtt.simple import MQTTClient

# Paramètres MQTT
SERVER = "192.168.1.2"  # Adresse IP du serveur MQTT
CLIENT_ID = "esp32_001"  # Identifiant du client MQTT
TOPIC_TEMPHUM = "maison/salon/th_sensor"
TOPIC_RELAY = "maison/salon/relay1"
TOPIC_RELAY2 = "maison/salon/relay2"
MQTT_USER = "client1"
MQTT_PASSWORD = "client1234"
# Paramètres de connexion au réseau WiFi
WIFI_SSID = "nyhome"
WIFI_PASSWORD = "bm@1574d"

# Broche du relais et du capteur DHT11
RELAY_PIN = 12
DHT_PIN = 27

# Fonction de connexion au réseau WiFi
def connect_wifi():
    import network
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print("Connexion au réseau WiFi...")
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        while not wlan.isconnected():
            pass
    print("Connecté au réseau WiFi :", wlan.ifconfig())

# Fonction de lecture du capteur DHT11 (température et humidité)

def read_sensor():
    dht_sensor = dht.DHT11(machine.Pin(DHT_PIN))
    dht_sensor.measure()
    return {
        "temperature": dht_sensor.temperature(),
        "humidity": dht_sensor.humidity()
    }

# Fonction de contrôle du relais
def control_relay(state):
    relay = machine.Pin(RELAY_PIN, machine.Pin.OUT)
    relay.value(state)

# Fonction de publication de la température et de l'humidité via MQTT
def publish_sensor_data(temperature, humidity):
    # Création du message en FORMAT DICTIONNAIRE PUIS JSON
    message = {
        "sensor_ID":1,
        "sensor_NAME": "DHT11",
        "temperature": temperature,
        "humidity": humidity
    }
    mqtt_client.publish(TOPIC_TEMPHUM, json.dumps(message))

# Fonction de CALLBACK MQTT pour le contrôle du relais
def on_message(topic, message):
    print("Topic:", topic, "message:", message)
    # Décodage du message binaire pour extraire le JSON
    try:
        json_message = json.loads(message.decode("utf-8"))
        # Extraction de l'état du relais et contrôle en conséquence
        if json_message["etat"] == "on":
            control_relay(1)
            print("Relais activé")
        elif json_message["etat"] == "off":
            control_relay(0)
            print("Relais désactivé")
    except Exception as e:
        print("Erreur lors du décodage du message :", e)

# Fonctionde CALL BACK avec controle des TOPICs :
def on_message_wct(topic, message):
    print("Topic:", topic, "message:", message)
    
    # Décodage du message binaire pour extraire le JSON
    try:
        json_message = json.loads(message.decode("utf-8"))
    except Exception as e:
        print("Erreur lors du décodage du message :", e)
        return
    
    # Test de (topic)
    if topic.decode('UTF-8') == TOPIC_RELAY:
        # Extraction de l'état du relais et contrôle en conséquence
        if "etat" in json_message:
            if json_message["etat"] == "on":
                control_relay(1)
                print("Relais activé")
            elif json_message["etat"] == "off":
                control_relay(0)
                print("Relais désactivé")
        else:
            print("Message JSON invalide : aucune clé 'etat' trouvée.")
    elif topic == TOPIC_RELAY2:
        if "etat" in json_message:
            if json_message["etat"] == "on":
                print("Relais 2 activé")
            elif json_message["etat"] == "off":
                print("Relais 2 désactivé")
    else :
        print("Sujet inconnu :", topic)

# Connexion au réseau WiFi
connect_wifi()

# Connexion au serveur MQTT
mqtt_client = MQTTClient(CLIENT_ID, SERVER, user=MQTT_USER, password=MQTT_PASSWORD)
#TOPIC LAST WILL (DERNIER MESSAGE EN CAS D UNE DECONNEXION ANORMALE)
topiclast = b"home/esp32/last"
msglast = b"ESP32 déconnectée !!!!"
mqtt_client.set_last_will(topiclast, msglast, retain=False, qos=0)
mqtt_client.set_callback(on_message_wct)
mqtt_client.connect()
mqtt_client.subscribe(TOPIC_RELAY)
mqtt_client.subscribe(TOPIC_RELAY2)

print("Connecté au serveur MQTT :", SERVER)

# Définir une variable pour stocker le moment du dernier envoi de données MQTT
last_publish_time = 0
periode_pub = 2000 # période de publication en ms
# Boucle principale
while True:
    try:
        # Vérifier si le temps écoulé depuis le dernier envoi est supérieur à 2 secondes
        if time.ticks_diff(time.ticks_ms(), last_publish_time) >= periode_pub:
            # Lecture de la température et de l'humidité
            sensor_data = read_sensor()
            temperature = sensor_data["temperature"]
            humidity = sensor_data["humidity"]
            print("Température :", temperature)
            print("Humidité :", humidity)
            
            # Publication des données du capteur via MQTT
            publish_sensor_data(temperature, humidity)
            
            # Mettre à jour le temps du dernier envoi
            last_publish_time = time.ticks_ms()
        
        # Vérification des messages MQTT
        mqtt_client.check_msg()
        
        # Attente courte pour éviter de surcharger le processeur
        time.sleep(0.1)
        
    except Exception as e:
        print("Erreur :", e)
        time.sleep(1)
NOCOMNCVCCGNDINLED1PWRRelay Module