diff --git a/modbus_gps001.py b/modbus_gps001.py new file mode 100755 index 0000000..6b8f343 --- /dev/null +++ b/modbus_gps001.py @@ -0,0 +1,232 @@ +#!/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() \ No newline at end of file