diff --git a/tools/rpi/README.md b/tools/rpi/README.md index 1027ccb0..bc8b23c0 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -86,7 +86,7 @@ Required python modules Some modules are not installed by default on a RaspberryPi, therefore add them manually: ``` -pip install crcmod pyyaml paho-mqtt +pip install crcmod pyyaml paho-mqtt SunTimes ``` Configuration diff --git a/tools/rpi/ahoy.yml.example b/tools/rpi/ahoy.yml.example index 644508e5..58866816 100644 --- a/tools/rpi/ahoy.yml.example +++ b/tools/rpi/ahoy.yml.example @@ -1,8 +1,12 @@ --- ahoy: - interval: 0 - sunset: true + interval: 5 + sunset: + disabled: false + latitude: 51.799118 + longitude: 10.615523 + altitude: 1142 # List of available NRF24 transceivers nrf: diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 0b558073..5f783ac4 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -10,24 +10,16 @@ import struct from enum import IntEnum import re import time +import traceback from datetime import datetime +from datetime import timedelta +from suntimes import SunTimes import argparse import yaml from yaml.loader import SafeLoader import paho.mqtt.client import hoymiles -def main_loop(do_init): - """Main loop""" - inverters = [ - inverter for inverter in ahoy_config.get('inverters', []) - if not inverter.get('disabled', False)] - - for inverter in inverters: - if hoymiles.HOYMILES_DEBUG_LOGGING: - print(f'Poll inverter {inverter["serial"]}') - poll_inverter(inverter, do_init) - class InfoCommands(IntEnum): InverterDevInform_Simple = 0 # 0x00 InverterDevInform_All = 1 # 0x01 @@ -48,6 +40,71 @@ class InfoCommands(IntEnum): GetSelfCheckState = 30 # 0x1e InitDataState = 0xff +class SunsetHandler: + def __init__(self, sunset_config): + self.suntimes = None + if sunset_config and sunset_config.get('disabled', True) == False: + latitude = sunset_config.get('latitude') + longitude = sunset_config.get('longitude') + altitude = sunset_config.get('altitude') + self.suntimes = SunTimes(longitude=longitude, latitude=latitude, altitude=altitude) + self.nextSunset = self.suntimes.setutc(datetime.now()) + print (f'Todays sunset is at {self.nextSunset}') + + def checkWaitForSunrise(self): + if not self.suntimes: + return + # if the sunset already happened for today + now = datetime.now() + if self.nextSunset < now: + # wait until the sun rises tomorrow + tomorrow = now + timedelta(days=1) + nextSunrise = self.suntimes.riseutc(tomorrow) + self.nextSunset = self.suntimes.setutc(tomorrow) + time_to_sleep = (nextSunrise - datetime.now()).total_seconds() + print (f'Waiting for sunrise at {nextSunrise} ({time_to_sleep} seconds)') + if time_to_sleep > 0: + time.sleep(time_to_sleep) + print (f'Woke up... next sunset is at {self.nextSunset}') + return + +def main_loop(ahoy_config): + """Main loop""" + inverters = [ + inverter for inverter in ahoy_config.get('inverters', []) + if not inverter.get('disabled', False)] + + sunset = SunsetHandler(ahoy_config.get('sunset')) + + loop_interval = ahoy_config.get('interval', 1) + try: + do_init = True + while True: + sunset.checkWaitForSunrise() + + t_loop_start = time.time() + + for inverter in inverters: + if hoymiles.HOYMILES_DEBUG_LOGGING: + print(f'Poll inverter {inverter["serial"]}') + poll_inverter(inverter, do_init) + do_init = False + + print('', end='', flush=True) + + if loop_interval > 0: + time_to_sleep = loop_interval - (time.time() - t_loop_start) + if time_to_sleep > 0: + time.sleep(time_to_sleep) + + except KeyboardInterrupt: + sys.exit() + except Exception as e: + print ('Exception catched: %s' % e) + traceback.print_exc() + raise + + def poll_inverter(inverter, do_init, retries=4): """ Send/Receive command_queue, initiate status poll on inverter @@ -310,25 +367,4 @@ if __name__ == '__main__': mqtt_client.subscribe(topic_item[1]) mqtt_command_topic_subs.append(topic_item) - loop_interval = ahoy_config.get('interval', 1) - try: - do_init = True - while True: - t_loop_start = time.time() - - main_loop(do_init) - - do_init = False - - print('', end='', flush=True) - - time_to_sleep = loop_interval - (time.time() - t_loop_start) - - if loop_interval > 0 and time_to_sleep > 0: - time.sleep(time_to_sleep) - - except KeyboardInterrupt: - sys.exit() - except Exception as e: - print ('Exception catched: %s' % e) - raise + main_loop(ahoy_config)