import asyncio import json import logging import os import paho.mqtt.client from huawei_solar import AsyncHuaweiSolar, ReadException from huawei_solar import register_values as rv from src.data import InverterData, ReadRegister from src.inverter import get_data from src.inverter_dummy import get_dummy_data from src.mqtt import connect DATA_MODE = os.getenv("DATA_MODE", "INVERTER") MQTT_TOPIC = os.getenv("MQTT_TOPIC", "inverter") FORCE_GET = os.getenv("FORCE_GET", False) slave_id = os.getenv("INVERTER_ID", 1) port = os.getenv("INVERTER_PORT", 502) host = os.getenv("INVERTER_HOST", "192.168.200.100") LOGGER = logging.getLogger(__name__) REQUEST_INTERVAL = 10 async def get_inverter_client() -> AsyncHuaweiSolar: inverter_client = await AsyncHuaweiSolar.create(host, port, slave_id) LOGGER.info( f"-- INVERTER -- Connected to Inverter on ip: {host}, port {port}" ) return inverter_client async def main(): inverter_client = await get_inverter_client() count = 0 while True: try: status = await inverter_client.get( ReadRegister.inverter_reg_status, slave_id ) except ReadException as error: LOGGER.error(f"Can't read register, {ReadRegister.inverter_reg_status}. " f"Error code: {error}. Sleep for 10 min") await asyncio.sleep(10*60) # Sleep 5 min LOGGER.info(f"-- INVERTER -- Status: {status}") if ( status.value == rv.DEVICE_STATUS_DEFINITIONS.get(0x0200) or FORCE_GET ): # Inverter is active, Get data LOGGER.info("-- INVERTER -- Send measured values") for register in ReadRegister.reg_to_read_measured: result = await get_inverter_data(inverter_client, register) send_data( mqtt_client, format_data_to_serialized_json(result), f"measure/{result.name}", ) if count == 6: # Every 1 min LOGGER.info("-- INVERTER -- Send calculated values") for register in ReadRegister.reg_to_read_calculated: result = await get_inverter_data(inverter_client, register) send_data( mqtt_client, format_data_to_serialized_json(result), f"calculated/{result.name}", ) if count == 30: # Every 5 min LOGGER.info("-- INVERTER -- Send status/alarm") for register in ReadRegister.reg_to_read_status: result = await get_inverter_data(inverter_client, register) send_data( mqtt_client, format_data_to_serialized_json(result), f"status/{result.name}", ) count = 0 else: LOGGER.debug("-- INVERTER -- Not Active, No need to read values") count += 1 LOGGER.info(f"Sleeping {REQUEST_INTERVAL}") await asyncio.sleep(REQUEST_INTERVAL) def send_data( client: paho.mqtt.client, storable_data: str, topic: str = "" ) -> None: try: LOGGER.debug( f"Sending data\ntopic: {MQTT_TOPIC + '/' + topic} \n" f"msg: {storable_data}" ) client.publish( MQTT_TOPIC + "/" + topic, payload=storable_data, qos=0, retain=False, ) except Exception: LOGGER.exception("ERROR PUBLISHING DATA TO MQTT BROKER.") def format_data_to_serialized_json(info: InverterData) -> str: data = {"value": info.value, "name": info.name, "unit": info.unit} json_obj = json.dumps(data) LOGGER.debug(f"json_obj: {json_obj}, type: {type(json_obj)}") return json_obj async def get_inverter_data( inverter_client: AsyncHuaweiSolar, register: str ) -> InverterData: if DATA_MODE == "INVERTER": data = await get_data(inverter_client, register, slave_id) return data else: data = await get_dummy_data() return data LOGGER.info("| === START === |") try: mqtt_client = connect() except TimeoutError: LOGGER.exception("---- CANT CONNECT ----") loop = asyncio.new_event_loop() try: asyncio.ensure_future(main(), loop=loop) loop.run_forever() except KeyboardInterrupt: pass finally: LOGGER.info("| === END === |") loop.close()