Inverter_huawei/src/main.py

144 lines
4.4 KiB
Python

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()