Igor Barcik 660ea7666f "Enhance PLC data monitoring and error handling"
Key changes include:

Improved error handling and logging in PLC data reading
Added detailed debug information with pprint
Restructured logging format for better readability
Removed redundant docstrings
Fixed PLC data reading logic with proper value extraction
Added support for extra properties in logger setup
Code cleanup and formatting improvements
2024-12-10 07:58:51 +01:00

123 lines
3.9 KiB
Python

import os
import pprint
import time
from datetime import datetime
from energy_monitor import CONN_STR, DatabaseManager, PlcManager
from logger_setup import setup_logger
# Globals
DEVICE_DELAY = 1 # Delay between device data fetches
POOL_RATE = 2 # 2s polling rate reading of NextRead value from database
FALLBACK_INTERVAL = 20 # 1h = 3600s interval in case db read issue
# Logger setup
logger = setup_logger()
def process_plc_devices(db_manager: DatabaseManager, plc_manager: PlcManager):
plc_configs = db_manager.get_plc_configs()
# If debug print out plc_configs to logs
logger.debug(
{
"msg": "Retrieved PLC configurations",
"plc_configs": [
{
"id": plc.id,
"ip": plc.ip,
"location": plc.location,
"is_enabled": plc.is_enabled,
"db_number": plc.db_number,
}
for plc in plc_configs
],
"timestamp": datetime.now().isoformat(),
},
)
for plc_config in plc_configs:
try:
if not plc_manager.check_connection(plc_config.ip):
logger.error(
{
"msg": "PLC connection failed",
"PlcId": plc_config.id,
"PlcIp": plc_config.ip,
"timestamp": datetime.now().isoformat(),
}
)
continue
air_value, energy_value, run_status = plc_manager.read_plc_data(plc_config)
db_manager.save_energy_data(plc_config.id, energy_value, air_value, True)
logger.info(
{
"msg": "✅ Data successfully read and saved",
"PlcId": plc_config.id,
"PlcIp": plc_config.ip,
"energy_value": energy_value,
"air_value": air_value,
"timestamp": datetime.now().isoformat(),
},
)
time.sleep(DEVICE_DELAY) # n-second delay between devices
except Exception as e:
logger.error(
{
"msg": "Error reading PLC data",
"PlcId": plc_config.id,
"PlcIp": plc_config.ip,
"error": str(e),
"timestamp": datetime.now().isoformat(),
},
)
def main():
db_manager = DatabaseManager(CONN_STR)
plc_manager = PlcManager()
pprint.pp(
{
"SQL_Config": {
"Server": os.getenv("DB_SERVER"),
"Database": os.getenv("DB_NAME"),
"User": os.getenv("DB_USER"),
# Masking password for security
"Password": "****",
},
"SEQ_Config": {
"URL": os.getenv("SEQ_URL"),
# Masking API key for security
"API_Key": "****",
},
"timestamp": datetime.now().isoformat(),
}
)
while True:
try:
scheduler_config = db_manager.get_scheduler_config()
if datetime.now() >= scheduler_config.next_read:
process_plc_devices(db_manager, plc_manager)
db_manager.update_next_read(scheduler_config.interval)
time.sleep(POOL_RATE)
except Exception as e:
logger.error(
{
"msg": "Main loop error! Falling back to 1h interval.",
"error": str(e),
"timestamp": datetime.now().isoformat(),
},
)
time.sleep(FALLBACK_INTERVAL) # Default fallback interval
if __name__ == "__main__":
main()