diff options
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | configstore.py | 51 | ||||
-rwxr-xr-x[-rw-r--r--] | inverter-bot (renamed from main.py) | 39 | ||||
-rw-r--r-- | isv.py | 42 | ||||
-rw-r--r-- | requirements.txt | 3 |
5 files changed, 37 insertions, 108 deletions
@@ -1,14 +1,18 @@ # inverter-bot -This is a Telegram bot for querying information from an InfiniSolar V family of hybrid solar inverters, in particular -inverters supported by **isv** utility, which is an older version of **infinisolarctl** from **infinisolar-tools** -package. +This is a Telegram bot for querying information from an InfiniSolar V family of hybrid solar inverters. It supports querying general status, such as battery voltage or power usage, printing amounts of energy generated in the last days, dumping status or rated information and more. It requires Python 3.6+ or so. +## Requirements + +- **`inverterd`** from [inverter-tools](https://github.com/gch1p/inverter-tools) +- **[`inverterd`](https://pypi.org/project/inverterd/)** python library +- Python 3.6+ or so + ## Configuration Configuration is stored in `config.ini` file in `~/.config/inverter-bot`. diff --git a/configstore.py b/configstore.py deleted file mode 100644 index fcaa5c8..0000000 --- a/configstore.py +++ /dev/null @@ -1,51 +0,0 @@ -import os, re -from configparser import ConfigParser - -CONFIG_DIR = os.environ['HOME'] + '/.config/inverter-bot' -CONFIG_FILE = 'config.ini' - -__config__ = None - - -def _get_config_path() -> str: - return "%s/%s" % (CONFIG_DIR, CONFIG_FILE) - - -def get_config(): - global __config__ - if __config__ is not None: - return __config__['root'] - - if not os.path.exists(CONFIG_DIR): - raise IOError("%s directory not found" % CONFIG_DIR) - - if not os.path.isdir(CONFIG_DIR): - raise IOError("%s is not a directory" % CONFIG_DIR) - - config_path = _get_config_path() - if not os.path.isfile(config_path): - raise IOError("%s file not found" % config_path) - - __config__ = ConfigParser() - with open(config_path) as config_content: - __config__.read_string("[root]\n" + config_content.read()) - - return __config__['root'] - - -def get_token() -> str: - return get_config()['token'] - - -def get_admins() -> tuple: - config = get_config() - return tuple([int(s) for s in re.findall(r'\b\d+\b', config['admins'], flags=re.MULTILINE)]) - - -def get_isv_bin() -> str: - return get_config()['isv_bin'] - - -def use_sudo() -> bool: - config = get_config() - return 'use_sudo' in config and config['use_sudo'] == '1'
\ No newline at end of file diff --git a/main.py b/inverter-bot index 1441728..a4cac30 100644..100755 --- a/main.py +++ b/inverter-bot @@ -1,10 +1,10 @@ -import logging -import re -import datetime -import isv -import configstore +#!/usr/bin/env python3 +import logging, re, datetime, json, inverterd +from typing import Optional +from argparse import ArgumentParser from html import escape +from pprint import pprint from time import sleep from strings import lang as _ from telegram import ( @@ -21,6 +21,7 @@ from telegram.ext import ( CallbackContext ) +inverter: Optional[inverterd.Client] = None # # helpers @@ -57,11 +58,12 @@ def start(update: Update, context: CallbackContext) -> None: def msg_status(update: Update, context: CallbackContext) -> None: try: - gs = isv.general_status() + gs = json.loads(inverter.exec('get-status'))['data'] + pprint(gs) # render response power_direction = gs['battery_power_direction'].lower() - power_direction = re.sub(r'ge$', 'ging', power_direction) + power_direction = re.sub(r'ges$', 'ging', power_direction) charging_rate = '' if power_direction == 'charging': @@ -162,15 +164,30 @@ def msg_all(update: Update, context: CallbackContext) -> None: if __name__ == '__main__': - config = configstore.get_config() - + # command-line arguments + parser = ArgumentParser() + parser.add_argument('--token', required=True, type=str, + help='Telegram bot token') + parser.add_argument('--users-whitelist', nargs='+', + help='ID of users allowed to use the bot') + parser.add_argument('--inverterd-host', default='127.0.0.1', type=str) + parser.add_argument('--inverterd-port', default=8305, type=int) + args = parser.parse_args() + + whitelist = list(map(lambda x: int(x), args.users_whitelist)) + + # connect to inverterd + inverter = inverterd.Client(host=args.inverterd_host, port=args.inverterd_port) + + # configure logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) - updater = Updater(configstore.get_token(), request_kwargs={'read_timeout': 6, 'connect_timeout': 7}) + # configure bot + updater = Updater(args.token, request_kwargs={'read_timeout': 6, 'connect_timeout': 7}) dispatcher = updater.dispatcher - user_filter = Filters.user(configstore.get_admins()) + user_filter = Filters.user(whitelist) dispatcher.add_handler(CommandHandler('start', start)) dispatcher.add_handler(MessageHandler(Filters.text(_('status')) & user_filter, msg_status)) @@ -1,42 +0,0 @@ -import subprocess -import configstore -import json - - -def __run(argv: list, fmt='json-w-units'): - argv.insert(0, configstore.get_isv_bin()) - if configstore.use_sudo(): - argv.insert(0, 'sudo') - argv.append('--format') - argv.append(fmt) - - result = subprocess.run(argv, capture_output=True) - if result.returncode != 0: - raise ChildProcessError("isv returned %d: %s" % (result.returncode, result.stderr)) - - return json.loads(result.stdout) if 'json' in fmt else result.stdout.decode('utf-8') - - -def general_status(as_table=False): - kwargs = {} - if as_table: - kwargs['fmt'] = 'table' - return __run(['--get-general-status'], **kwargs) - - -def day_generated(y: int, m: int, d: int): - return __run(['--get-day-generated', str(y), str(m), str(d)]) - - -def rated_information(as_table=False): - kwargs = {} - if as_table: - kwargs['fmt'] = 'table' - return __run(['--get-rated-information'], **kwargs) - - -def faults(as_table=False): - kwargs = {} - if as_table: - kwargs['fmt'] = 'table' - return __run(['--get-faults-warnings'], **kwargs) diff --git a/requirements.txt b/requirements.txt index ccd058e..1fd4f8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -python-telegram-bot~=13.1
\ No newline at end of file +python-telegram-bot~=13.1 +inverterd
\ No newline at end of file |