srne-mqtt/srnemqtt/__main__.py

119 lines
4.0 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
from logging import getLogger
from logging import root as logging_root
from logging.config import dictConfig as loggingDictConfig
from bluepy.btle import BTLEDisconnectError # type: ignore
from serial import SerialException # type: ignore
from .config import get_config, get_consumers, get_interface
from .protocol import ChargeController
from .util import LazyJSON, LoggingDictFilter, Periodical
logger = getLogger("SolarMPPT")
class CommunicationError(BTLEDisconnectError, SerialException, IOError):
pass
def main():
conf = get_config()
loggingDictConfig(conf.get("logging", {}))
logging_dict_filter = LoggingDictFilter()
logging_dict_filter.data["service"] = "SolarMPPT"
logging_root.addFilter(logging_dict_filter)
consumers = get_consumers(conf)
per_voltages = Periodical(interval=15)
per_current_hist = Periodical(interval=60)
try:
while True:
try:
logger.info("Connecting...")
with get_interface() as dev:
cc = ChargeController(dev)
logging_dict_filter.data["srne_model"] = cc.model
logging_dict_filter.data["srne_version"] = cc.version
logging_dict_filter.data["srne_serial"] = cc.serial
logger.info("Connected.")
logger.info(f"Controller model: {cc.model}")
logger.info(f"Controller version: {cc.version}")
logger.info(f"Controller serial: {cc.serial}")
for consumer in consumers:
consumer.controller = cc
# write(dev, construct_request(0, 32))
# Memory dump
# for address in range(0, 0x10000, 16):
# log(f"Reading 0x{address:04X}...")
# write(wd, construct_request(address, 16))
extra = cc.extra
days = extra.run_days
res = cc.today.as_dict()
res.update(extra.as_dict())
for consumer in consumers:
consumer.write(res)
del extra
# Historical data isn't actually used anywhere yet
# Limit to 4 days for now
for i in range(min(days, 4)):
hist = cc.get_historical(i)
res = hist.as_dict()
logger.debug(LazyJSON({i: res}))
for consumer in consumers:
consumer.write({str(i): res})
while True:
now = time.time()
if per_voltages(now):
data = cc.state.as_dict()
logger.debug(LazyJSON(data))
for consumer in consumers:
consumer.write(data)
if per_current_hist(now):
data = cc.today.as_dict()
data.update(cc.extra.as_dict())
logger.debug(LazyJSON(data))
for consumer in consumers:
consumer.write(data)
# print(".")
for consumer in consumers:
consumer.poll()
time.sleep(max(0, 1 - (time.time() - now)))
# if STATUS.get('load_enabled'):
# write(wd, CMD_DISABLE_LOAD)
# else:
# write(wd, CMD_ENABLE_LOAD)
except CommunicationError:
logger.error("Disconnected")
time.sleep(1)
except (KeyboardInterrupt, SystemExit, Exception) as e:
for consumer in consumers:
consumer.exit()
if type(e) is not KeyboardInterrupt:
raise
if __name__ == "__main__":
main()