From 1c9cd6a447b5d51b24c8cf050c9a473e2af5f256 Mon Sep 17 00:00:00 2001 From: Adolfo Delorenzo Date: Sat, 3 Aug 2024 18:58:02 -0600 Subject: [PATCH] 2024-08-03 - --- modbus_gps002.py | 253 +++++++++++++++++++++++++++++++++++++++ modbus_gps_with_reset.py | 3 - 2 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 modbus_gps002.py diff --git a/modbus_gps002.py b/modbus_gps002.py new file mode 100644 index 0000000..d87f054 --- /dev/null +++ b/modbus_gps002.py @@ -0,0 +1,253 @@ +#!/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): + """ + Initializes the GPS device by sending necessary commands and checking the response. + """ + try: + # Send configuration commands to the GPS + commands = [ + b'AT+CGNSPWR=1\r', # Power on the GPS + b'AT+CGNSSEQ="RMC"\r', # Configure the data sequence + b'AT+CGNSTST=1\r' # Start data transmission + ] + + for cmd in commands: + gps_ser.write(cmd) + time.sleep(2) # Increased delay + response = gps_ser.read(100) + logging.info(f"GPS command {cmd} response: {response}") + + if b'ERROR' in response: + logging.error(f"GPS initialization error for command {cmd}") + return False + + logging.info("GPS initialized successfully") + return True + + except Exception as e: + logging.error(f"Error initializing GPS: {e}") + return False + +def read_gps_data(gps_ser): + """ + Reads GPS data and returns it as a string. + """ + try: + gps_ser.write(b'AT+CGNSINF\r') + time.sleep(1) + response = gps_ser.read(200) + + if b'+CGNSINF:' in response: + # Extract the GPS data from the response + gps_data = response.split(b'+CGNSINF: ')[1].strip() + logging.info(f"GPS data read: {gps_data}") + return gps_data.decode('ascii') + else: + logging.warning(f"Unexpected GPS response: {response}") + return None + 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: + # Process GPS data here if needed + publish_to_mqtt(f"iiot/{myhost}/gps", gps_data) + write_to_influxdb(gps_data) + 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) + if initialize_gps(gps_ser): + logging.info("Devices reinitialized successfully") + else: + logging.error("Failed to reinitialize GPS") + 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) + if not initialize_gps(gps_ser): + logging.error("Failed to initialize GPS. Continuing without GPS functionality.") + + 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 + publish_to_mqtt(f"iiot/{myhost}/temperature", temp) + publish_to_mqtt(f"iiot/{myhost}/humidity", hum) + publish_to_mqtt(f"iiot/{myhost}/door/pin17", str(status_17)) + + # Try to publish pending data + for item in pending_data: + publish_to_mqtt(f"iiot/{myhost}/temperature", item["temperature"]) + publish_to_mqtt(f"iiot/{myhost}/humidity", item["humidity"]) + publish_to_mqtt(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() diff --git a/modbus_gps_with_reset.py b/modbus_gps_with_reset.py index e061527..d8fb199 100644 --- a/modbus_gps_with_reset.py +++ b/modbus_gps_with_reset.py @@ -27,9 +27,6 @@ mqtt_client = mqtt.Client(myhost) mqtt_client.connect(mqttBroker, 1883) # Modbus configuration -#preferred_device = '/dev/ttyUSB0' -#fallback_device = '/dev/ttyUSB5' -#device_path = preferred_device if os.path.exists(preferred_device) else fallback_device modbus_device = '/dev/modbus' mb_address = 1