#!/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()