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
123 lines
3.9 KiB
Python
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()
|