def get_encryption_key(key_file=None): """ Encryption key for symmetric encryption. URL-safe base64-encoded 32-byte key * Get local key, or exec wizard for making one. :param: key_file: :str: path of the file with the encryption key :return: :bytes: encryption_key """ if key_file is None: key_file = os.path.join(DATA_PATH, CONFIG.get('BROADCAST', 'KEY_FILE', fallback='.secret_key')) try: secret_key = open(key_file).read().encode() except FileNotFoundError: print('\033[0m\033[1m\033[34mCrypto KEY is missing.\033[0m Please, select one option:\n' '\t\033[1m1. Generate a new key.\n\t2. Input an existent key. (Copy&paste from another computer)') selec = input('\033[34mOPTION: \033[0m\033[31m') if selec == '1': secret_key = Fernet.generate_key() else: secret_key = input('*** KEY: ').encode() if len(secret_key) > 10: print('\033[0mThe new KEY ("{}")\nwill be saved in "{}"\n'.format(secret_key, key_file)) open(key_file, 'wb').write(secret_key) else: print('\033[31;1mNot a valid KEY!:\n"{}". Try again... BYE!\033[0m'.format(secret_key)) sys.exit(-1) return secret_key
def test_main_cli_data_plots(self): """ CLI Testing patching sys.argv with unittest.mock """ from enerpi.command_enerpi import enerpi_main_cli from enerpi.base import CONFIG dir_plots = os.path.join(self.DATA_PATH, CONFIG.get('ENERPI_DATA', 'IMG_BASEPATH')) self.exec_func_with_sys_argv(enerpi_main_cli, ['test_cli', '-f', '2016-10-01::2016-10-01', '-p', 'png', '-po', 'rm=30s'], test_mode=True) self.exec_func_with_sys_argv(enerpi_main_cli, ['test_cli', '-f', '::2016-10-04', '-p', 'png', '-po', 'rm=1h'], test_mode=True) self.exec_func_with_sys_argv(enerpi_main_cli, ['test_cli', '-f', '2016-10-25::2016-10-26', '-p', 'png', '-po', 'rs=30s'], test_mode=True) self.exec_func_with_sys_argv(enerpi_main_cli, ['test_cli', '-f', '2016-10-25::2016-10-30', '-p', 'png', '-po', 'rs=3min'], test_mode=True) self.exec_func_with_sys_argv(enerpi_main_cli, ['test_cli', '-f', '2016-10-21::2016-10-31', '-p', 'png', '-po', 'rs=30min'], test_mode=True) self.exec_func_with_sys_argv(enerpi_main_cli, ['test_cli', '-f', '2016-10-10::2016-10-30', '-p', 'png', '-po', 'rs=15min'], test_mode=True) # To get the plots for inspection: # os.system('cp -R {}/ ~/Desktop/test_plots'.format(dir_plots)) self.assertEqual(len(os.listdir(dir_plots)), 6)
def make_cron_command_task_daemon(): """ CRON periodic task for exec ENERPI LOGGER as daemon at every boot Example command: */15 * * * * sudo -u www-data /home/pi/PYTHON/py35/bin/python /home/pi/PYTHON/py35/lib/python3.5/site-packages/enerpiweb/mule_rscgen.py -o :return: :str: cron_command """ # cmd_logger = '@reboot sudo -u {user_logger} {python_pathbin}/enerpi-daemon start' cmd_logger = 'sudo -u {user_logger} {python_pathbin}/enerpi-daemon start' local_params = dict(user_logger=CONFIG.get('ENERPI_DATA', 'USER_LOGGER', fallback='pi'), python_pathbin=os.path.dirname(sys.executable)) return cmd_logger.format(**local_params)
def test_www_data_in_rpi(): """ Test for check user & groups membership needed to run ENERPI with: · The ENERPI logger daemon, running every reboot with CRON · The ENERPI flask webserver, running under NGINX + UWSGI-EMPEROR """ from enerpi.base import CONFIG def _formatted_test(user_t, groups_t, fix=False): print('*' * 80 + '\nTEST (u="{}", g="{}", fix=False):'.format(user_t, groups_t)) res = _check_user_groups(user=user_t, desired_groups=groups_t, fix=fix) print('********** TEST RESULT = {} **********'.format(res) + '\n' + '*' * 80) return res if sys.platform == 'linux': # RPI only test user_logger = CONFIG.get('ENERPI_DATA', 'USER_LOGGER', fallback='www-data') user_web = CONFIG.get('ENERPI_WEBSERVER', 'USER_SERVER', fallback='www-data') needed_groups = [('spi', ), ('gpio', 'kmem')] for user in [user_logger, user_web]: print('\nCHECKING GROUPS MEMBERSHIP FOR USER "{}"'.format(user)) groups_exist = _checkoutput(['groups'])[1].split() user_exists, user_groups = _get_user_groups(user) print('EXISTENT GROUPS: "{}"'.format(groups_exist)) print('GROUPS WITH USER {} (exist={}): "{}"'.format(user, user_exists, user_groups)) assert user_exists for need in needed_groups: print('need: {}'.format(need)) for g in need: print('analysis g={}'.format(g)) if g in groups_exist: print('{} in groups_exist'.format(g)) result = _formatted_test(user, [g], fix=True) print('user: {} in group: {}? {}--> '.format(user, g, result)) assert result break
def _get_pb_obj(): # Lazy load global PBOBJ if PBOBJ is None: try: pushbullet_token = CONFIG.get('NOTIFY', 'PUSHBULLET_TOKEN') if not pushbullet_token: raise InvalidKeyError PBOBJ = Pushbullet(pushbullet_token) except (NoOptionError, NoSectionError, InvalidKeyError) as e: log('NO Pushbullet config ({} [{}])' .format(e, e.__class__), 'error', False) PBOBJ = None return PBOBJ
def test_1_streaming(self): def _print_next_msg(counter, iterator): msg = next(iterator) print('** STREAM MSG {}:\n{}\n --> T_{:.3f} secs'.format(counter, msg, time() - tic)) tic = time() r = self.endpoint_request('api/stream/realtime', mimetype_check='text/event-stream', status_check=200) print('headers={}\nmimetype={}'.format(r.headers, r.mimetype)) assert r.is_streamed assert not r.stream.closed toc_get = time() print('GET took {:.4f} s'.format(toc_get - tic)) print('En STREAMING, DATA_PATH:{}, listdir:\n{}'.format(self.DATA_PATH, os.listdir(self.DATA_PATH))) from enerpi.base import CONFIG key_file_now = os.path.join(self.DATA_PATH, CONFIG.get('BROADCAST', 'KEY_FILE', fallback='.secret_key')) print('KEY_FILE_now: {}'.format(key_file_now)) try: print('KEY_now: {}'.format(open(key_file_now).read())) except FileNotFoundError as e: # Problema de .secret_key ya importada! print(e) it = r.stream.response.iter_encoded() counter_received = 0 for i in range(math.ceil(1.5 * self.stream_max_time)): try: _print_next_msg(i, it) counter_received += 1 except StopIteration as e: print(e.__class__) self.assertGreater(counter_received, 1) assert not r.stream.closed r.stream.close() assert r.stream.closed
def get_encryption_key(key_file=None): """ Encryption key for symmetric encryption. URL-safe base64-encoded 32-byte key * Get local key, or exec wizard for making one. :param: key_file: :str: path of the file with the encryption key :return: :bytes: encryption_key """ if key_file is None: key_file = os.path.join( DATA_PATH, CONFIG.get('BROADCAST', 'KEY_FILE', fallback='.secret_key')) try: secret_key = open(key_file).read().encode() except FileNotFoundError: print( '\033[0m\033[1m\033[34mCrypto KEY is missing.\033[0m Please, select one option:\n' '\t\033[1m1. Generate a new key.\n\t2. Input an existent key. (Copy&paste from another computer)' ) selec = input('\033[34mOPTION: \033[0m\033[31m') if selec == '1': secret_key = Fernet.generate_key() else: secret_key = input('*** KEY: ').encode() if len(secret_key) > 10: print('\033[0mThe new KEY ("{}")\nwill be saved in "{}"\n'.format( secret_key, key_file)) open(key_file, 'wb').write(secret_key) else: print( '\033[31;1mNot a valid KEY!:\n"{}". Try again... BYE!\033[0m'. format(secret_key)) sys.exit(-1) return secret_key
show_pi_temperature, set_logging_conf, log, FILE_LOGGING, LOGGING_LEVEL) from enerpi.database import init_catalog, save_raw_data, HDF_STORE_PATH from enerpi.pisampler import enerpi_sampler_rms, enerpi_raw_sampler, msg_to_dict, tuple_to_dict_json from enerpi.iobroadcast import get_codec, broadcast_msg, receiver_msg_generator from enerpi.ledrgb import get_rgbled, led_info, led_alarm, blink_color from enerpi.notifier import push_enerpi_error # Disk data store N_SAMPLES_BUFFER_DISK = CONFIG.getint('ENERPI_DATA', 'N_SAMPLES_BUFFER_DISK', fallback=60) STORE_PERIODIC_CATALOG_SEC = CONFIG.getint('ENERPI_DATA', 'STORE_PERIODIC_CATALOG_SEC', fallback=3600) INIT_LOG_MARK = CONFIG.get('ENERPI_SAMPLER', 'INIT_LOG_MARK', fallback='INIT') # Variable global para controlar el estado de notificaciones vía RGB LED LED_STATE = 0 PALETA = dict(off=(0., (0., 0., 1.)), standby=(250., (0., 1., 0.)), medium=(750., (1., .5, 0.)), high=(3500., (1., 0., 0.)), max=(4500., (1., 0., 1.))) # Decay control # (# of samples/s dropping a lot sometimes # --> y = -a * x**2. x(9:32)=1300, x(9:37)=1190, x(9:48)=995) MIN_N_SAMPLES_DELTA_FRACTION = .5 MIN_N_SAMPLES_MAX_CONSIDERED = 900
- Process or clear log files - Method for appending raw data to ENERPI catalog from the ENERPI Logger ... """ import datetime as dt import os import pandas as pd from time import time import re from enerpi.base import CONFIG, DATA_PATH, log, timeit, SENSORS from enerpi.catalog import EnerpiCatalog # Config: INIT_LOG_MARK = CONFIG.get('ENERPI_SAMPLER', 'INIT_LOG_MARK', fallback='INIT ENERPI') HDF_STORE = CONFIG.get('ENERPI_DATA', 'HDF_STORE') HDF_STORE_PATH = os.path.join(DATA_PATH, HDF_STORE) KEY = CONFIG.get('ENERPI_DATA', 'KEY', fallback='/rms') CONFIG_CATALOG = dict(raw_file=HDF_STORE, key_raw_data=KEY, key_summary_data='/hours', key_summary_extra='/days', check_integrity=True, archive_existent=False, verbose=False) def init_catalog(sensors=None, base_path=DATA_PATH, **kwargs): """
# -*- coding: utf-8 -*- """ ENERPI - Broadcast receiver & emitter """ from cryptography.fernet import Fernet, InvalidToken from binascii import Error import os import socket import sys from time import time from enerpi.base import DATA_PATH, CONFIG, log # LAN broadcasting _UDP_IP = CONFIG.get('BROADCAST', 'UDP_IP', fallback="192.168.1.255") _DESCRIPTION_IO = "\tSENDER - RECEIVER vía UDP. Broadcast IP: {}, PORT: {}" def get_encryption_key(key_file=None): """ Encryption key for symmetric encryption. URL-safe base64-encoded 32-byte key * Get local key, or exec wizard for making one. :param: key_file: :str: path of the file with the encryption key :return: :bytes: encryption_key """ if key_file is None: key_file = os.path.join( DATA_PATH,
""" from enerpi.base import CONFIG, log, CONFIG_FILENAME import datetime as dt # dateutil included in python-dateutil # noinspection PyPackageRequirements from dateutil.parser import parse # PINOUT RGB_LED WITH_RGBLED = CONFIG.getboolean('RGBLED', 'WITH_RGBLED', fallback=False) PIN_R = CONFIG.getint('RGBLED', 'PIN_R', fallback=19) PIN_G = CONFIG.getint('RGBLED', 'PIN_G', fallback=20) PIN_B = CONFIG.getint('RGBLED', 'PIN_B', fallback=16) # Horario de funcionamiento del RGB LED LED_TIME_ON = CONFIG.get('RGBLED', 'TIME_ON', fallback=None) LED_TIME_OFF = CONFIG.get('RGBLED', 'TIME_OFF', fallback=None) if LED_TIME_ON is not None: LED_TIME_ON = parse(LED_TIME_ON) if LED_TIME_OFF is not None: LED_TIME_OFF = parse(LED_TIME_OFF) def _use_led(): if LED_TIME_ON and LED_TIME_OFF: if LED_TIME_ON.time() < dt.datetime.now().time() < LED_TIME_OFF.time(): return True return False return True
'show_switch_comments': True, }, 'sensors': { 'order': 1, 'filename': 'sensors_enerpi.json', 'text_button': '<i class="fa fa-wrench" aria-hidden="true"></i> SENSORS', 'show_switch_comments': False, }, 'encryption_key': { 'order': 2, 'filename': os.path.join( DATA_PATH, CONFIG.get('BROADCAST', 'KEY_FILE', fallback='.secret_key')), 'text_button': '<i class="fa fa-user-secret" aria-hidden="true"></i> Secret Key', 'show_switch_comments': False, }, } TITLE_EDIT_CRYPTOKEY = 'Encryption KEY' SUBTITLE_EDIT_CRYPTOKEY = 'KEY_FILE' TITLE_EDIT_JS_SENSORS = 'SENSORS' SUBTITLE_EDIT_JS_SENSORS = 'SENSORS' OPTIONAL_PARAMS = ['PUSHBULLET_TOKEN', 'EMAIL_RECIPIENT']
from flask_autodoc import Autodoc from flask_mail import Mail from werkzeug.contrib.fixers import ProxyFix from werkzeug.routing import Rule import jinja2 import os # noinspection PyUnresolvedReferences from enerpi import __version__ from enerpi.base import (CONFIG, DATA_PATH, check_resource_files, GMAIL_ACCOUNT, GMAIL_APP_PASSWORD) from enerpi.api import get_encryption_key basedir = os.path.abspath(os.path.dirname(__file__)) STATIC_PATH = os.path.join( DATA_PATH, CONFIG.get('ENERPI_WEBSERVER', 'STATIC_PATH', fallback='WWW')) LOGGING_LEVEL_SERVER = CONFIG.get( 'ENERPI_WEBSERVER', 'LOGGING_LEVEL_WEB', fallback='DEBUG') SERVER_FILE_LOGGING = os.path.join( STATIC_PATH, CONFIG.get( 'ENERPI_WEBSERVER', 'FILE_LOGGING_WEB', fallback='enerpiweb.log')) PREFIX_WEB = CONFIG.get('ENERPI_WEBSERVER', 'PREFIX_WEB', fallback='/enerpi') BASECOLOR = '#{}'.format( CONFIG.get('ENERPI_WEBSERVER', 'BASECOLOR_HEX', fallback='0CBB43')) check_resource_files( STATIC_PATH, os.path.join(basedir, 'static'), verbose=False) # WITH_WEB = CONFIG.getboolean('ENERPI_WEBSERVER', 'WITH_WEBSERVER', # fallback=True) WITH_ML_SUBSYSTEM = CONFIG.getboolean('ENERPI_WEBSERVER', 'WITH_ML', fallback=False)
ENERPI_CONFIG_FILES = { 'config': { 'order': 0, 'filename': 'config_enerpi.ini', 'text_button': '<i class="fa fa-check-square-o" aria-hidden="true"></i> ENERPI config', 'show_switch_comments': True, }, 'sensors': { 'order': 1, 'filename': 'sensors_enerpi.json', 'text_button': '<i class="fa fa-wrench" aria-hidden="true"></i> SENSORS', 'show_switch_comments': False, }, 'encryption_key': { 'order': 2, 'filename': os.path.join(DATA_PATH, CONFIG.get('BROADCAST', 'KEY_FILE', fallback='.secret_key')), 'text_button': '<i class="fa fa-user-secret" aria-hidden="true"></i> Secret Key', 'show_switch_comments': False, }, } TITLE_EDIT_CRYPTOKEY = 'Encryption KEY' SUBTITLE_EDIT_CRYPTOKEY = 'KEY_FILE' TITLE_EDIT_JS_SENSORS = 'SENSORS' SUBTITLE_EDIT_JS_SENSORS = 'SENSORS' OPTIONAL_PARAMS = ['PUSHBULLET_TOKEN', 'EMAIL_RECIPIENT'] def _web_edit_enerpi_config_ini(lines_ini_file): """
- Install configuration & CRON task for web resources generation - Uninstall CRON task - Run Flask server """ import argparse import os import sys from enerpi.base import BASE_PATH, DATA_PATH, CONFIG, log, check_resource_files, NGINX_CONFIG_FILE, UWSGI_CONFIG_FILE from enerpi.prettyprinting import print_secc, print_cyan, print_red, print_magenta FLASK_WEBSERVER_PORT = CONFIG.getint('ENERPI_WEBSERVER', 'FLASK_WEBSERVER_PORT', fallback=7777) PERIOD_MINUTES_RSC_GEN = CONFIG.getint('ENERPI_WEBSERVER', 'RSC_GEN_EVERY_MINUTES', fallback=15) USER_SERVER = CONFIG.get('ENERPI_WEBSERVER', 'USER_SERVER', fallback='www-data') basedir = os.path.abspath(os.path.dirname(__file__)) def make_cron_command_task_periodic_rscgen(): """ CRON task for generate web resources with enerpiplot.mule_rscgen.py Example command: */15 * * * * sudo -u www-data /home/pi/PYTHON/py35/bin/python /home/pi/PYTHON/py35/lib/python3.5/site-packages/enerpiweb/mule_rscgen.py -o :return: :str: cron_command """ # cmd_server = '*/{period} * * * * ...' cmd_server = 'sudo -u {user_server} {python_pathbin}/python3 {path_enerpiplot}/mule_rscgen.py -o' local_params = dict(path_enerpiplot=os.path.abspath(os.path.join(BASE_PATH, '..', 'enerpiplot')),
def enerpi_main_cli(test_mode=False): """ Uso de ENERPI desde CLI enerpi -h para mostrar las diferentes opciones """ # CLI Arguments args = _enerpi_arguments() verbose = not args.silent if args.version: return __version__ # CONTROL LOGIC # Shows RPI Temps timer_temps = show_pi_temperature(args.temps, 3, args.timeout) if args.install or args.uninstall: from enerpi.config.crontasks import set_command_on_reboot, clear_cron_commands # INSTALL / UNINSTALL CRON TASKS & KEY cmd_logger = make_cron_command_task_daemon() if args.install: # Logging configuration set_logging_conf(FILE_LOGGING, LOGGING_LEVEL, True) log('** Installing CRON task for start logger at reboot:\n"{}"'.format(cmd_logger), 'ok', True, False) set_command_on_reboot(cmd_logger, verbose=verbose) try: os.chmod(DATA_PATH, 0o777) [os.chmod(os.path.join(base, f), 0o777) for base, dirs, files in os.walk(DATA_PATH) for f in files + dirs] except PermissionError: log("Can't set 777 permissions on {0}/* files...\nDo it manually, please: 'sudo chmod 777 -R {0}'" .format(DATA_PATH), 'warning', True, False) else: log('** Deleting CRON task for start logger at reboot:\n"{}"'.format(cmd_logger), 'warn', True, False) clear_cron_commands([cmd_logger], verbose=verbose) elif (args.enerpi or args.info or args.backup or args.reprocess or args.config or args.raw or args.last or args.clearlog or args.filter or args.plot or args.plot_tiles): # Init CLI # import matplotlib # matplotlib.use('Agg') import matplotlib.pyplot as plt import pandas as pd pd.set_option('display.width', 200) # Logging configuration set_logging_conf(FILE_LOGGING, LOGGING_LEVEL, True) # Shows INI config & SENSORS if args.config: import json log('ENERPI Configuration (from INI file in "{}"):' .format(os.path.join(DATA_PATH, CONFIG_FILENAME)), 'ok', True, False) for s in CONFIG.sections(): log('* Section {}:'.format(s), 'info', True, False) for opt in CONFIG.options(s): log('{:27} -->\t{}'.format(opt.upper(), CONFIG.get(s, opt)), 'debug', True, False) log('*' * 80 + '\n', 'ok', True, False) log('\nENERPI SENSORS Config (from JSON file in "{}"):' .format(os.path.join(DATA_PATH, SENSORS_CONFIG_JSON_FILENAME)), 'ok', True, False) json_content = json.loads(open(os.path.join(DATA_PATH, SENSORS_CONFIG_JSON_FILENAME), 'r').read()) log('\n'.join(['{}'.format(s) for s in json_content]), 'magenta', True, False) log('--> {}\n\n'.format(SENSORS), 'ok', True, False) # Delete LOG File if args.clearlog: from enerpi.database import delete_log_file delete_log_file(FILE_LOGGING, verbose=verbose) # Data Store Config _existe_st, path_st = _check_store_relpath(args.store) # Starts ENERPI Logger if args.enerpi: from enerpi.enerpimeter import enerpi_logger # Demo logger if args.demo: set_logging_conf(FILE_LOGGING + '_demo.log', LOGGING_LEVEL, True) path_st = os.path.join(DATA_PATH, 'debug_buffer_disk.h5') enerpi_logger(is_demo=args.demo, verbose=verbose, path_st=path_st, delta_sampling=args.delta, roll_time=args.window, sampling_ms=args.ts, timeout=args.timeout) elif args.backup: from enerpi.database import init_catalog # Export data to CSV: catalog = init_catalog(sensors=SENSORS, raw_file=path_st, check_integrity=False, verbose=verbose, test_mode=test_mode) export_ok = catalog.export_chunk(args.backup) log('EXPORT OK? {}'.format(export_ok), 'ok' if export_ok else 'error', True, False) elif args.reprocess: from enerpi.database import init_catalog # Re-process all data in catalog catalog = init_catalog(sensors=SENSORS, raw_file=path_st, check_integrity=False, verbose=verbose, test_mode=test_mode) repro_ok = catalog.reprocess_all_data() log('REPROCESS OK? {}'.format(repro_ok), 'ok' if repro_ok else 'error', verbose, verbose) # TODO revisar config X11 + ssh -X para plot en display local elif args.raw: from enerpi.enerpimeter import enerpi_raw_data # Raw mode delta_secs = args.raw raw_data = enerpi_raw_data(path_st.replace('.h5', '_raw_sample.h5'), delta_secs=delta_secs, use_dummy_sensors=args.demo, roll_time=args.window, sampling_ms=args.ts, verbose=verbose) t0, tf = raw_data.index[0], raw_data.index[-1] log('Showing RAW DATA for {} seconds ({} samples, {:.2f} sps)\n** Real data: from {} to {} --> {:.2f} sps' .format(delta_secs, len(raw_data), len(raw_data) / delta_secs, t0, tf, len(raw_data) / (tf-t0).total_seconds()), 'info', verbose, False) raw_data.plot(lw=.5, figsize=(16, 10)) plt.show() # Shows database info elif args.info or args.filter or args.plot or args.plot_tiles: from enerpi.database import init_catalog, show_info_data catalog = init_catalog(sensors=SENSORS, raw_file=path_st, check_integrity=False, verbose=verbose, test_mode=test_mode) if args.plot_tiles: from enerpiplot.enerplot import gen_svg_tiles ok = gen_svg_tiles(IMG_TILES_BASEPATH, catalog, color=COLOR_TILES if not test_mode else (1, 0, 0)) if ok: log('SVG Tiles generated!', 'ok', verbose, True) else: log('No generation of SVG Tiles!', 'error', verbose, True) else: data, consumption = _extract_time_slice_from_args(args.filter, args.info, catalog) if (args.info or args.filter) and data is not None and not data.empty: show_info_data(data, consumption) if (args.plot and (data is not None) and not data.empty and (consumption is not None) and not consumption.empty): from enerpiplot.enerplot import plot_power_consumption_hourly rs_data, rm_data, path_saveimg, show = _extract_plot_params_from_args(args.plot, args.plot_options) mean_sensor_data = data[SENSORS.columns_sensors_mean] if SENSORS.columns_sensors_mean else None log('Generate PLOT with RESAMPLE={}, ROLLING={}, show={}, path_save="{}"' .format(rs_data, rm_data, show, path_saveimg), 'info', verbose, False) img_name = plot_power_consumption_hourly(data[SENSORS.columns_sensors_rms], consumption.kWh, data_mean_s=mean_sensor_data, rs_data=rs_data, rm_data=rm_data, show=show, path_saveimg=path_saveimg) if img_name is not None: log('IMAGE saved in "{}"'.format(img_name), 'ok', verbose, False) # Shows database info else: # Shows last 10 entries from enerpi.database import get_ts_last_save last = get_ts_last_save(path_st, get_last_sample=True, verbose=verbose, n=10) log('Showing last 10 entries in {}:\n{}'.format(path_st, last), 'info', verbose, False) # Shows & extract info from LOG File elif args.log: from enerpi.database import extract_log_file data_log = extract_log_file(FILE_LOGGING, extract_temps=True, verbose=verbose) try: df_temps = data_log[data_log.temp.notnull()].drop(['tipo', 'msg', 'debug_send'], axis=1).dropna(axis=1) if len(set(df_temps['exec'])) == 1: df_temps = df_temps.drop(['exec'], axis=1) path_csv = os.path.join(DATA_PATH, 'debug_rpitemps.csv') if not df_temps.empty: df_temps.to_csv(path_csv) print('*** Saved temperature data extracted from LOG in {}'.format(path_csv)) except AttributeError: print('No se encuentran datos de Tª de RPI en el LOG') # Demo sender elif args.demo: from enerpi.enerpimeter import enerpi_logger set_logging_conf(FILE_LOGGING + '_demo.log', LOGGING_LEVEL, True) path_st = os.path.join(DATA_PATH, 'debug_buffer_disk.h5') enerpi_logger(is_demo=True, verbose=verbose, path_st=path_st, delta_sampling=args.delta, roll_time=args.window, sampling_ms=args.ts, timeout=args.timeout) # Receiver else: # elif args.receive: from enerpi.enerpimeter import receiver log('{}\n {}'.format(PRETTY_NAME, DESCRIPTION), 'ok', verbose, False) receiver(verbose=verbose, timeout=args.timeout, port=args.port) if timer_temps is not None: log('Stopping RPI TEMPS sensing...', 'debug', True) timer_temps.cancel() log('Exiting from ENERPI CLI...', 'debug', True) if not test_mode: sys.exit(0)
ENERPI - CLI methods & argument parser """ import datetime as dt import os import re import sys from enerpi import PRETTY_NAME, DESCRIPTION, __version__ from enerpi.base import (IMG_TILES_BASEPATH, DATA_PATH, CONFIG, SENSORS, CONFIG_FILENAME, SENSORS_CONFIG_JSON_FILENAME, FILE_LOGGING, LOGGING_LEVEL, set_logging_conf, log, show_pi_temperature, DEFAULT_IMG_MASK, COLOR_TILES) # Config: UDP_PORT = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) HDF_STORE = CONFIG.get('ENERPI_DATA', 'HDF_STORE') def _enerpi_arguments(): """ CLI Parser """ import argparse p = argparse.ArgumentParser(description="\033[1m\033[5m\033[32m{}\033[0m\n{}\n\n".format(PRETTY_NAME, DESCRIPTION), epilog='\033[34m\n*** By default, ENERPI starts as receiver (-r) ***\n' + '\033[0m', formatter_class=argparse.RawTextHelpFormatter) g_m = p.add_argument_group(title='☆ \033[1m\033[4mENERPI Working Mode\033[24m', description='→ Choose working mode between RECEIVER / SENDER') g_m.add_argument('-e', '--enerpi', action='store_true', help='⚡ SET ENERPI LOGGER & BROADCAST MODE') g_m.add_argument('-r', '--receive', action='store_true', help='⚡ SET Broadcast Receiver mode (by default)')
import pandas as pd from threading import Timer from time import sleep, time from enerpi.base import (CONFIG, SENSORS, DATA_PATH, TimerExiter, show_pi_temperature, set_logging_conf, log, FILE_LOGGING, LOGGING_LEVEL) from enerpi.database import init_catalog, save_raw_data, HDF_STORE_PATH from enerpi.pisampler import enerpi_sampler_rms, enerpi_raw_sampler, msg_to_dict, tuple_to_dict_json from enerpi.iobroadcast import get_codec, broadcast_msg, receiver_msg_generator from enerpi.ledrgb import get_rgbled, led_info, led_alarm, blink_color from enerpi.notifier import push_enerpi_error # Disk data store N_SAMPLES_BUFFER_DISK = CONFIG.getint('ENERPI_DATA', 'N_SAMPLES_BUFFER_DISK', fallback=60) STORE_PERIODIC_CATALOG_SEC = CONFIG.getint('ENERPI_DATA', 'STORE_PERIODIC_CATALOG_SEC', fallback=3600) INIT_LOG_MARK = CONFIG.get('ENERPI_SAMPLER', 'INIT_LOG_MARK', fallback='INIT') # Variable global para controlar el estado de notificaciones vía RGB LED LED_STATE = 0 PALETA = dict(off=(0., (0., 0., 1.)), standby=(250., (0., 1., 0.)), medium=(750., (1., .5, 0.)), high=(3500., (1., 0., 0.)), max=(4500., (1., 0., 1.))) # Decay control # (# of samples/s dropping a lot sometimes # --> y = -a * x**2. x(9:32)=1300, x(9:37)=1190, x(9:48)=995) MIN_N_SAMPLES_DELTA_FRACTION = .5 MIN_N_SAMPLES_MAX_CONSIDERED = 900
# -*- coding: utf-8 -*- """ ENERPI - Broadcast receiver & emitter """ from cryptography.fernet import Fernet, InvalidToken from binascii import Error import os import socket import sys from time import time from enerpi.base import DATA_PATH, CONFIG, log # LAN broadcasting _UDP_IP = CONFIG.get('BROADCAST', 'UDP_IP', fallback="192.168.1.255") _DESCRIPTION_IO = "\tSENDER - RECEIVER vía UDP. Broadcast IP: {}, PORT: {}" def get_encryption_key(key_file=None): """ Encryption key for symmetric encryption. URL-safe base64-encoded 32-byte key * Get local key, or exec wizard for making one. :param: key_file: :str: path of the file with the encryption key :return: :bytes: encryption_key """ if key_file is None: key_file = os.path.join(DATA_PATH, CONFIG.get('BROADCAST', 'KEY_FILE', fallback='.secret_key'))
""" import argparse import os import sys from enerpi.base import BASE_PATH, DATA_PATH, CONFIG, log, check_resource_files, NGINX_CONFIG_FILE, UWSGI_CONFIG_FILE from enerpi.prettyprinting import print_secc, print_cyan, print_red, print_magenta FLASK_WEBSERVER_PORT = CONFIG.getint('ENERPI_WEBSERVER', 'FLASK_WEBSERVER_PORT', fallback=7777) PERIOD_MINUTES_RSC_GEN = CONFIG.getint('ENERPI_WEBSERVER', 'RSC_GEN_EVERY_MINUTES', fallback=15) USER_SERVER = CONFIG.get('ENERPI_WEBSERVER', 'USER_SERVER', fallback='www-data') basedir = os.path.abspath(os.path.dirname(__file__)) def make_cron_command_task_periodic_rscgen(): """ CRON task for generate web resources with enerpiplot.mule_rscgen.py Example command: */15 * * * * sudo -u www-data /home/pi/PYTHON/py35/bin/python /home/pi/PYTHON/py35/lib/python3.5/site-packages/enerpiweb/mule_rscgen.py -o :return: :str: cron_command """ # cmd_server = '*/{period} * * * * ...' cmd_server = 'sudo -u {user_server} {python_pathbin}/python3 {path_enerpiplot}/mule_rscgen.py -o'
from flask import Flask from flask_autodoc import Autodoc from flask_mail import Mail from werkzeug.contrib.fixers import ProxyFix from werkzeug.routing import Rule import jinja2 import os # noinspection PyUnresolvedReferences from enerpi import __version__ from enerpi.base import (CONFIG, DATA_PATH, check_resource_files, GMAIL_ACCOUNT, GMAIL_APP_PASSWORD) from enerpi.api import get_encryption_key basedir = os.path.abspath(os.path.dirname(__file__)) STATIC_PATH = os.path.join( DATA_PATH, CONFIG.get('ENERPI_WEBSERVER', 'STATIC_PATH', fallback='WWW')) LOGGING_LEVEL_SERVER = CONFIG.get('ENERPI_WEBSERVER', 'LOGGING_LEVEL_WEB', fallback='DEBUG') SERVER_FILE_LOGGING = os.path.join( STATIC_PATH, CONFIG.get('ENERPI_WEBSERVER', 'FILE_LOGGING_WEB', fallback='enerpiweb.log')) PREFIX_WEB = CONFIG.get('ENERPI_WEBSERVER', 'PREFIX_WEB', fallback='/enerpi') BASECOLOR = '#{}'.format( CONFIG.get('ENERPI_WEBSERVER', 'BASECOLOR_HEX', fallback='0CBB43')) check_resource_files(STATIC_PATH, os.path.join(basedir, 'static'), verbose=False)