from ina219 import INA219, DeviceRangeError
from time import sleep
from datetime import datetime
import matplotlib.pyplot as plt
import signal
import sys

REFRESH_RATE = 0.01
SAMPLES = 100

# INA219 setup
try:
    # Create INA219 instance with highest possible precision
    ina_voltage = INA219(shunt_ohms=0.1, max_expected_amps=0.1, address=0x40, busnum=1)
    ina_voltage.configure(ina_voltage.RANGE_16V, ina_voltage.GAIN_1_40MV)
except Exception as e:
    print(f"Error initializing INA219: {e}")
    sys.exit(1)

# Dictionaries for storing measurements
voltage_samples = []
averaged_voltages = []
timestamps = []

# Read voltage
def read():
    try:
        # Calculate actual voltage
        voltage = ina_voltage.voltage() + ina_voltage.shunt_voltage() / 1000
        voltage_samples.append(voltage)

        # If enough samples are reached, print and store average
        if len(voltage_samples) >= SAMPLES:
            average_voltage = sum(voltage_samples) / len(voltage_samples)
            voltage_samples.clear()

            timestamp = datetime.now().strftime('%d.%m.%Y %H:%M:%S')
            averaged_voltages.append(average_voltage)
            timestamps.append(timestamp)

            print(f"[{timestamp}] Voltage: {average_voltage:.3f} V")

    except DeviceRangeError as ex:
        print(f"Device Range Error: {ex}")

# On cancel draw graph with all averaged measurements
def signal_handler(sig, frame):
    print("\nDrawing graph...")

    if averaged_voltages:
        plt.figure(figsize=(10, 5))
        plt.plot(averaged_voltages, marker='o', linestyle='-')
        plt.title('Voltage Over Time')
        plt.xlabel('Index')
        plt.ylabel('Voltage')
        plt.grid(True)
        plt.tight_layout()
        filename = f'voltage_{datetime.now().strftime("%d%m%Y_%H%M%S")}.png'
        plt.savefig(filename)
        print(f"Graph saved at: '{filename}'")
    else:
        print("No voltage data collected.")

    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

# Loop until cancel
while True:
    read()
    sleep(REFRESH_RATE)