144 lines
4.4 KiB
Python
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()
|