#!/usr/bin/env python3 # -*- coding:utf-8 -*- import RPi.GPIO as GPIO import paho.mqtt.client as mqtt import os import minimalmodbus import time import serial from datetime import datetime from influxdb_client import InfluxDBClient, Point from influxdb_client.client.write_api import SYNCHRONOUS import logging import subprocess # Set up logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') # GPIO configuration GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.cleanup() # MQTT Broker settings mqttBroker = "65.108.199.212" myhost = os.uname()[1] mqtt_client = mqtt.Client(myhost) mqtt_client.connect(mqttBroker, 1883) # Modbus configuration modbus_device = '/dev/modbus' mb_address = 1 sensy_boi = minimalmodbus.Instrument(modbus_device, mb_address) sensy_boi.serial.baudrate = 9600 sensy_boi.serial.bytesize = 8 sensy_boi.serial.parity = minimalmodbus.serial.PARITY_NONE sensy_boi.serial.stopbits = 1 sensy_boi.serial.timeout = 0.5 sensy_boi.mode = minimalmodbus.MODE_RTU sensy_boi.clear_buffers_before_each_transaction = True sensy_boi.close_port_after_each_call = True # GPS configuration gps_device = '/dev/ttyUSB3' # InfluxDB settings INFLUXDB_URL = "http://100.64.024:6" INFLUXDB_TOKEN = "IPtqPXbaXuuMHvx_tOt1cmIZfLHucd-9DcepXTVpQc-fNKBhp6pkhyTsq_XnoGXdxwILy5AFFgZ_QUZCE5Jhg==" INFLUXDB_ORG = "juandiego" INFLUXDB_BUCKET = "gpsdata" # Initialize InfluxDB client influx_client = InfluxDBClient(url=INFLUXDB_URL, token=INFLUXDB_TOKEN, org=INFLUXDB_ORG) write_api = influx_client.write_api(write_options=SYNCHRONOUS) # GPIO pin configuration PIN_17 = 17 LuzPuerta = 18 GPIO_25 = 25 GPIO.setup(PIN_17, GPIO.IN) GPIO.setup(LuzPuerta, GPIO.OUT) GPIO.setup(GPIO_25, GPIO.OUT) # Pending data list pending_data = [] def control_gpio(): status_17 = GPIO.input(PIN_17) if status_17 == GPIO.LOW: GPIO.output(LuzPuerta, GPIO.HIGH) # Red light on else: GPIO.output(LuzPuerta, GPIO.LOW) return status_17 def initialize_gps(gps_ser): """ Inicializa el dispositivo GPS enviando los comandos necesarios para configurarlo. """ try: # Enviar comandos de configuración al GPS gps_ser.write(b'AT+CGNSPWR=1\r') # Encender el GPS time.sleep(2) # Aumentar el tiempo de espera gps_ser.write(b'AT+CGNSSEQ="RMC"\r') # Configurar la secuencia de datos time.sleep(2) # Aumentar el tiempo de espera gps_ser.write(b'AT+CGNSTST=1\r') # Iniciar la transmisión de datos time.sleep(2) # Aumentar el tiempo de espera # Leer la respuesta del GPS para asegurarse de que está funcionando response = gps_ser.read(100) logging.info(f"GPS initialized with response: {response}") except Exception as e: logging.error(f"Error initializing GPS: {e}") def read_gps_data(gps_ser): """ Lee los datos del GPS y los devuelve como una cadena. """ try: gps_ser.write(b'AT+CGNSINF\r') time.sleep(1) response = gps_ser.read(200) logging.info(f"GPS data read: {response}") return response except Exception as e: logging.error(f"Error reading GPS data: {e}") return None def publish_to_mqtt(topic, payload): """ Publica un mensaje en el broker MQTT. """ try: mqtt_client.publish(topic, payload) logging.info(f"Published to MQTT topic {topic}: {payload}") except Exception as e: logging.error(f"Error publishing to MQTT: {e}") def write_to_influxdb(data): """ Escribe los datos en InfluxDB. """ try: point = Point("gps_data").tag("host", myhost).field("data", data) write_api.write(bucket=INFLUXDB_BUCKET, org=INFLUXDB_ORG, record=point) logging.info(f"Data written to InfluxDB: {data}") except Exception as e: logging.error(f"Error writing to InfluxDB: {e}") def get_gps_position(gps_ser): """ Obtiene la posición GPS. """ gps_data = read_gps_data(gps_ser) if gps_data: # Procesar los datos GPS aquí si es necesario return True return False def reset_usb_ports(): """ Resetea los puertos USB. """ try: subprocess.run(["usbreset", "/dev/bus/usb/001/001"], check=True) logging.info("USB ports reset successfully") except Exception as e: logging.error(f"Error resetting USB ports: {e}") def reinitialize_devices(): """ Re-inicializa los dispositivos. """ try: global sensy_boi, gps_ser sensy_boi = minimalmodbus.Instrument(modbus_device, mb_address) gps_ser = serial.Serial(gps_device, baudrate=9600, timeout=1) initialize_gps(gps_ser) logging.info("Devices reinitialized successfully") except Exception as e: logging.error(f"Error reinitializing devices: {e}") def main(): try: # Initialize GPS gps_ser = serial.Serial(gps_device, baudrate=9600, timeout=1) initialize_gps(gps_ser) reset_counter = 0 while True: try: # Control GPIO status_17 = control_gpio() # Read Modbus data try: temp = sensy_boi.read_register(0, 1) # Example register for temperature hum = sensy_boi.read_register(1, 1) # Example register for humidity # Try to publish current data mqtt_client.publish(f"iiot/{myhost}/temperature", temp) mqtt_client.publish(f"iiot/{myhost}/humidity", hum) mqtt_client.publish(f"iiot/{myhost}/door/pin17", str(status_17)) # Try to publish pending data for item in pending_data: mqtt_client.publish(f"iiot/{myhost}/temperature", item["temperature"]) mqtt_client.publish(f"iiot/{myhost}/humidity", item["humidity"]) mqtt_client.publish(f"iiot/{myhost}/door/pin17", item["door_status"]) pending_data.clear() # Clear the list if all data was published except Exception as e: logging.error(f"Error publishing data to MQTT: {str(e)}") pending_data.append({ "temperature": temp, "humidity": hum, "door_status": str(status_17) }) # Save data in memory # Print processed data logging.info("-------------------------------------") logging.info(f"Temperature = {temp:.1f}°C") logging.info(f"Relative humidity = {hum:.1f}%") logging.info(f"Door status (PIN 17) = {status_17}") logging.info("-------------------------------------") except Exception as e: logging.error(f"Error reading Modbus data: {str(e)}") # Get GPS position if not get_gps_position(gps_ser): logging.warning("Failed to get GPS position") reset_counter += 1 if reset_counter >= 60: # Reset every 30 minutes (60 * 30 seconds) reset_usb_ports() reinitialize_devices() reset_counter = 0 time.sleep(30) except KeyboardInterrupt: logging.info("Program interrupted by user") except Exception as e: logging.error(f"Unexpected error: {str(e)}") finally: GPIO.cleanup() gps_ser.close() influx_client.close() if __name__ == "__main__": main()