from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from ina219 import INA219
from ina219 import DeviceRangeError
import time
import logging
import socket

SHUNT_OHMS = 0.1
errors_counter = 0
success_counter = 0
power_off = 0
prefix = "ds5"  # define your prefix here
UDP_IP = "192.168.20.122"
UDP_PORT = 5555

def read():
    ina = INA219(SHUNT_OHMS)
    ina.configure()
    volts = ina.voltage()
    print('aku_volts {}'.format(volts))
    return volts

def send_to_udp(message):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(message.encode(), (UDP_IP, UDP_PORT))

def read_modbus():
    global errors_counter, success_counter, power_off

    client = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600, stopbits=1, parity='N', bytesize=8, timeout=10)
    if not client.connect():
        print_error()
        return

    rr = client.read_holding_registers(0, 15)
    if rr.isError():
        print_error()
    else:
        value = rr.registers
        volts = float(value[0]) / 10
        watts = float(value[3])

        # Read from INA219
        aku_volts = read()

        # Combine all the values into one message
        message = '{}_volts {} {}_watts {} {}_aku_volts {} {}_power_off {}'.format(prefix, volts, prefix, watts, prefix, aku_volts, prefix, power_off)
        print(message)

        # send messages to UDP
        send_to_udp(message)

        errors_counter = 0  # reset error counter on successful reading
        success_counter += 1
        if success_counter == 3 and power_off == 1:
            power_off = 0
            success_counter = 0
            print("Power restored!")
            power_restored_message = '{}_power_restored {}'.format(prefix, power_off)
            send_to_udp(power_restored_message)

    client.close()

def print_error():
    global errors_counter, success_counter, power_off

    # Read from INA219 and include aku_volts in the message
    aku_volts = read()

    success_counter = 0  # reset success counter on error
    errors_counter += 1
    if errors_counter >= 3:
        if power_off == 0:
            print("Power off alert")
        power_off = 1
        power_off_message = '{}_power_off {} {}_aku_volts {}'.format(prefix, power_off, prefix, aku_volts)
        send_to_udp(power_off_message)
    else:
        # If it's a general error (not a power off alert), include aku_volts in the message
        error_message = '{}_error 1 {}_aku_volts {}'.format(prefix, prefix, aku_volts)
        send_to_udp(error_message)

while True:
    read_modbus()
    time.sleep(10)
