#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Read modbus data from Ginlong Solis inverter
# and format for sending with zabbix_trapper
#
# Based on https://sequr.be/blog/2021/08/reading-ginlong-solis-inverter-over-serial-and-importing-in-home-assistant-over-mqtt/
#
import logging
import minimalmodbus
#import paho.mqtt.client as mqtt
import serial
import socket
import sys
import time

# zabbix_trapper requires hostname be sent with each item
zabbixagentname = "solisinverter"

logging.basicConfig(stream=sys.stderr, level=logging.INFO)

def modbus_connect():
  instrument = minimalmodbus.Instrument('/dev/ttyUSB0',1) # Set to inverter's address
  instrument.serial.baudrate = 9600
  instrument.serial.bytesize = 8
  instrument.serial.parity   = serial.PARITY_NONE
  instrument.serial.stopbits = 1
  instrument.serial.timeout  = 3
  #instrument.debug = True
  return instrument

def modbus_read(instrument):

  # get data from solis
  # all of the registers are shifted by -1: if you want to read register 3005, ask for 3004!
  Realtime_ACW = instrument.read_long(3004, functioncode=4, signed=False) # Read AC Watts as Unsigned 32-Bit
  print(zabbixagentname, "solis.acwatts", Realtime_ACW)

  Realtime_DCV1 = instrument.read_register(3021, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.string1.v", Realtime_DCV1)

  Realtime_DCV2 = instrument.read_register(3023, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.string2.v", Realtime_DCV2)

  Realtime_DCI = instrument.read_register(3022, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.string1.i", Realtime_DCI)

  Realtime_DCI1 = instrument.read_register(3024, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.string2.i", Realtime_DCI1)  

  Realtime_ACV = instrument.read_register(3035, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.gridv", Realtime_ACV)
  
  Realtime_ACI = instrument.read_register(3038, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.gridi", Realtime_ACI)

  Realtime_ACF = instrument.read_register(3042, number_of_decimals=2, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.gridfreq", Realtime_ACF)
  
  Inverter_C = instrument.read_register(3041, number_of_decimals=1, functioncode=4, signed=True) 
  print(zabbixagentname, "solis.invtemp", Inverter_C)
  
  AlltimeEnergy_KW = instrument.read_long(3008, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.genalltime", AlltimeEnergy_KW)
  
  Today_KW = instrument.read_register(3014, number_of_decimals=1, functioncode=4, signed=False) 
  print(zabbixagentname, "solis.gentoday", Today_KW)


def main():
  try:
    modc = modbus_connect()
    data = modbus_read(modc)

  except TypeError as err:
    logging.error("TypeError:\n{}".format(err))

  except ValueError as err:
    logging.error("ValueError:\n{}".format(err))

  except minimalmodbus.NoResponseError as err:
    logging.error("Modbus no response:\n{}".format(err))

  except serial.SerialException as err:
    logging.error("SerialException:\n{}".format(err))

  except Exception as err:
    logging.error("Exception:\n{}".format(err))

if __name__ == "__main__":
  main()
