2024-08-03 -
This commit is contained in:
parent
859b545717
commit
36d1e9c401
232
modbus_gps001.py
Executable file
232
modbus_gps001.py
Executable file
@ -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()
|
Loading…
Reference in New Issue
Block a user