#!/usr/bin/python3 # -*- coding: utf-8 -*- # https://github.com/karioja/vedirect # https://github.com/halcy/Mastodon.py # Command: python3 solar_bot.py --port /dev/ttyUSB0 import settings import argparse, os, time, datetime from vedirect import Vedirect from mastodon import Mastodon from apscheduler.schedulers.background import BackgroundScheduler scheduler = BackgroundScheduler() scheduler.start() # DB 1 is used as DB 0 is used by mastodon import redis r = redis.Redis(host='localhost', port=6379, db=1, decode_responses=True) import logging logging.basicConfig(encoding='utf-8', level=logging.INFO) # This needs to be uncommented on first run and then commented out after that - obviously there is a better way to do this. #Mastodon.create_app( # 'pytooterapp', # api_base_url = instance_url, # to_file = 'pytooter_clientcrednew.secret' #) def mastodon_login(): mastodon = Mastodon(client_id = settings.access_client_id,) mastodon.log_in( settings.mastodon_user, settings.mastodon_password, to_file = settings.access_secret ) def print_data_callback(packet): r.set('batt_v', packet['V']) r.set('main_current', packet['I']) r.set('panel_voltage',packet['VPV']) r.set('panel_power',packet['PPV']) r.set('load_current',packet['IL']) r.set('yield_today',packet['H20']) r.set('max_power_today',packet['H21']) r.set('yield_yesterday',packet['H22']) r.set('max_power_yesterday',packet['H23']) def get_shutdown(): fp = open('/run/systemd/shutdown/scheduled') data = fp.readlines() fp.close() shutdown_date = data[0].split('=')[1].rstrip() ts = int(shutdown_date) / 1000000 time_now = int(time.time()) shutdown_date = datetime.datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') time_to_shutdown = ts - time_now time_to_date = datetime.datetime.utcfromtimestamp(time_to_shutdown).strftime('%H:%M:%S') warning_time = ts - 600 warning_to_date = datetime.datetime.utcfromtimestamp(warning_time).strftime('%Y-%m-%d %H:%M:%S') return shutdown_date, time_to_date, warning_to_date def warn_shutdown(): try: mastodon = Mastodon(access_token = settings.access_secret, api_base_url = settings.instance_url) mastodon.toot('Warning\nSystem Shutdown in 10minutes') except: logging.info('Failed to send toot') def send_toot(): logging.info('Preparing Toot') try: batt_v_V = int(r.get('batt_v')) / 1000 main_current = r.get('main_current') panel_voltage = int(r.get('panel_voltage')) / 1000 panel_power = r.get('panel_power') load_current = int(r.get('load_current')) / 1000 yield_today = int(r.get('yield_today')) / 1000 max_power_today = r.get('max_power_today') load_power = load_current * batt_v_V final_date, time_date, warning_time = get_shutdown() toot_to_send = 'Solarcene.community Power Data\nBattery Voltage: {}V\nBattery Current: {}mA\nPanel Voltage: {}V\nPanel Power: {}W\nLoad Current: {}A\nLoad Power: {}W\nYield Today: {}kWh\nMax Power Today: {}W\nUpdated every 60 minutes\n\nShutdown planned for {}UTC (in {})'.format(batt_v_V, main_current, panel_voltage, panel_power, load_current, load_power, yield_today, max_power_today, final_date, time_date) logging.info(toot_to_send) except: logging.info('Failed to construct toot') try: mastodon = Mastodon(access_token = settings.access_secret, api_base_url = settings.instance_url) mastodon.toot(toot_to_send) except: logging.info('Failed to send toot') def start_toot(): logging.info('Sleeping for 60 seconds to allow mastodon to fully start') time.sleep(60) try: final_date, time_date, warning_time = get_shutdown() mastodon = Mastodon(access_token = settings.access_secret, api_base_url = settings.instance_url) mastodon.toot('System Online\n\nShutdown planned for: {}UTC (in {})'.format(final_date, time_date)) except: logging.info('Failed to send toot') if __name__ == '__main__': parser = argparse.ArgumentParser(description='Process VE.Direct protocol') parser.add_argument('--port', help='Serial port') parser.add_argument('--timeout', help='Serial port read timeout', type=int, default='60') args = parser.parse_args() scheduler.add_job(send_toot, trigger='cron', minute=1) logging.info('Starting') mastodon_login() logging.info('Logged In') os.system("shutdown -h 20:15") final_date, time_date, warning_time = get_shutdown() print(warning_time) scheduler.add_job(warn_shutdown, trigger='date', run_date=warning_time ) start_toot() ve = Vedirect(args.port, args.timeout) ve.read_data_callback(print_data_callback) logging.info('Exit')