def test_ledrgb(self): """ RGB LED Testing :return: """ from enerpi.base import CONFIG from enerpi.ledrgb import get_rgbled, led_alarm, led_info, blink_color led = get_rgbled(verbose=True) if led is None: # 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) print('ERROR!! NO RGB LED. (WITH_LED={}; PINOUT_RGB=({},{},{})'.format(with_rgbled, pin_r, pin_g, pin_b)) # assert 0 else: print('TESTING RGB LED!') led_alarm(led, timeout=0) sleep(1) led_info(led, n=3) sleep(3) led_alarm(led, time_blinking=2.5, timeout=3) sleep(4) led_info(led, n=2) sleep(4) led_alarm(led, timeout=0) sleep(2) led_info(led, n=1) sleep(3) # Blinking: blink_color(led, (1, 0, 0), n=1) sleep(1) blink_color(led, (0, 1, 0), n=2) sleep(1) blink_color(led, (0, 0, 1), n=3) sleep(1) blink_color(led, (1, 1, 0), n=1) sleep(1) blink_color(led, (1, 0, 1), n=2) sleep(1) blink_color(led, (0, 1, 1), n=3) sleep(1) blink_color(led, (1, 1, 1), n=1) sleep(2) print('OK!!') led.close()
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 test_0_config(self): from enerpi.base import CONFIG print(self.tmp_dir) print(self.DATA_PATH) print(self.cat) print(CONFIG.sections()) for s in ['ENERPI_DATA', 'ENERPI_WEBSERVER', 'ENERPI_SAMPLER', 'BROADCAST', 'RGBLED']: pp.print_cyan(list(CONFIG[s].keys())) pp.print_red(list(CONFIG[s].values()))
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 receiver_msg_generator(verbose=True, n_msgs=None, port=None, codec=None): """ Generador de mensajes en el receptor de la emisión en la broadcast IP. Recibe los mensajes y los desencripta. También devuelve los tiempos implicados en la recepción (~ el ∆T entre mensajes) y el proceso de desencriptado. :param verbose: :bool: Imprime Broadcast IP & PORT. :param n_msgs: :int: # de mensajes a recibir (ilimitados por defecto). :param port: :int: # de puerto de escucha. :param codec: :Fernet obj: Fernet object for decrypting msgs. :yield: msg, ∆T_msg, ∆T_decryp """ if port is None: port = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) if codec is None: codec = get_codec(get_encryption_key()) sock, counter = None, 0 udp_ip = _UDP_IP try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: sock.bind((udp_ip, port)) except OSError as e: log('OSError --> {}. IP={}, PORT={}'.format(e, udp_ip, port), 'error', verbose) raise KeyboardInterrupt log(_DESCRIPTION_IO.format(udp_ip, port), 'ok', verbose) while (n_msgs is None) or (counter < n_msgs): tic = time() data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes toc_msg = time() try: msg = codec.decrypt(data).decode() except InvalidToken as e: log( 'InvalidToken ERROR: {}. La clave es correcta?\n* KEY: "{}"' .format(e, get_encryption_key()), 'error', verbose, True) break toc_dcry = time() yield msg, toc_msg - tic, toc_dcry - toc_msg counter += 1 # log('Closing receiver_msg_generator socket...', 'debug', verbose, True) # except OSError as e: # log('OSError {} en receiver_msg_generator'.format(e), 'error', verbose, True) except KeyboardInterrupt: log('KeyboardInterrupt en receiver_msg_generator', 'warn', verbose, True) if sock is not None: sock.close() raise StopIteration
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 broadcast_msg(msg, counter_unreachable, sock_send=None, codec=None, port=None, verbose=True): """ Emisión de datos en modo broadcast UDP (para múltiples receptores) como mensaje de texto encriptado. :param msg: Cadena de texto a enviar. :param counter_unreachable: np.array([0, 0]) de control de emisiones incorrectas (seguidas y totales) :param sock_send: Socket de envío broadcast. Se devuelve para su reutilización. :param codec: :Fernet obj: Fernet object for encrypting msgs. :param port: # de puerto de retransmisión. :param verbose: Imprime en stout mensajes de error y de envío de datos :return: sock_send """ def _get_broadcast_socket(verb=False): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) log(_DESCRIPTION_IO.format(_UDP_IP, port), 'ok', verb, verb) return sock if codec is None: codec = get_codec() if port is None: port = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) if sock_send is None: sock_send = _get_broadcast_socket() encrypted_msg_b = codec.encrypt(msg.encode()) try: sock_send.sendto(encrypted_msg_b, (_UDP_IP, port)) counter_unreachable[0] = 0 except OSError as e: # [Errno 101] Network is unreachable if counter_unreachable[0] % 3 == 0: log( 'OSError: {}; C_UNREACHABLE: {}'.format( e, counter_unreachable), 'warn', verbose) counter_unreachable += 1 sock_send = None # except Exception as e: # log('ERROR en sendto: {} [{}]'.format(e, e.__class__), 'err', verbose) # sock_send = _get_broadcast_socket() # sock_send.sendto(encrypted_msg_b, (_UDP_IP, UDP_PORT)) log('SENDED: {}'.format(msg), 'debug', verbose, False) return sock_send
def receiver_msg_generator(verbose=True, n_msgs=None, port=None, codec=None): """ Generador de mensajes en el receptor de la emisión en la broadcast IP. Recibe los mensajes y los desencripta. También devuelve los tiempos implicados en la recepción (~ el ∆T entre mensajes) y el proceso de desencriptado. :param verbose: :bool: Imprime Broadcast IP & PORT. :param n_msgs: :int: # de mensajes a recibir (ilimitados por defecto). :param port: :int: # de puerto de escucha. :param codec: :Fernet obj: Fernet object for decrypting msgs. :yield: msg, ∆T_msg, ∆T_decryp """ if port is None: port = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) if codec is None: codec = get_codec(get_encryption_key()) sock, counter = None, 0 udp_ip = _UDP_IP try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: sock.bind((udp_ip, port)) except OSError as e: log('OSError --> {}. IP={}, PORT={}'.format(e, udp_ip, port), 'error', verbose) raise KeyboardInterrupt log(_DESCRIPTION_IO.format(udp_ip, port), 'ok', verbose) while (n_msgs is None) or (counter < n_msgs): tic = time() data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes toc_msg = time() try: msg = codec.decrypt(data).decode() except InvalidToken as e: log('InvalidToken ERROR: {}. La clave es correcta?\n* KEY: "{}"' .format(e, get_encryption_key()), 'error', verbose, True) break toc_dcry = time() yield msg, toc_msg - tic, toc_dcry - toc_msg counter += 1 # log('Closing receiver_msg_generator socket...', 'debug', verbose, True) # except OSError as e: # log('OSError {} en receiver_msg_generator'.format(e), 'error', verbose, True) except KeyboardInterrupt: log('KeyboardInterrupt en receiver_msg_generator', 'warn', verbose, True) if sock is not None: sock.close() raise StopIteration
def broadcast_msg(msg, counter_unreachable, sock_send=None, codec=None, port=None, verbose=True): """ Emisión de datos en modo broadcast UDP (para múltiples receptores) como mensaje de texto encriptado. :param msg: Cadena de texto a enviar. :param counter_unreachable: np.array([0, 0]) de control de emisiones incorrectas (seguidas y totales) :param sock_send: Socket de envío broadcast. Se devuelve para su reutilización. :param codec: :Fernet obj: Fernet object for encrypting msgs. :param port: # de puerto de retransmisión. :param verbose: Imprime en stout mensajes de error y de envío de datos :return: sock_send """ def _get_broadcast_socket(verb=False): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) log(_DESCRIPTION_IO.format(_UDP_IP, port), 'ok', verb, verb) return sock if codec is None: codec = get_codec() if port is None: port = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) if sock_send is None: sock_send = _get_broadcast_socket() encrypted_msg_b = codec.encrypt(msg.encode()) try: sock_send.sendto(encrypted_msg_b, (_UDP_IP, port)) counter_unreachable[0] = 0 except OSError as e: # [Errno 101] Network is unreachable if counter_unreachable[0] % 3 == 0: log('OSError: {}; C_UNREACHABLE: {}'.format(e, counter_unreachable), 'warn', verbose) counter_unreachable += 1 sock_send = None # except Exception as e: # log('ERROR en sendto: {} [{}]'.format(e, e.__class__), 'err', verbose) # sock_send = _get_broadcast_socket() # sock_send.sendto(encrypted_msg_b, (_UDP_IP, UDP_PORT)) log('SENDED: {}'.format(msg), 'debug', verbose, False) return sock_send
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_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
'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']
- 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): """
import numpy as np import os 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)
def enerpi_logger(path_st=HDF_STORE_PATH, delta_sampling=SENSORS.delta_sec_data, roll_time=SENSORS.rms_roll_window_sec, sampling_ms=SENSORS.ts_data_ms, timeout=None, is_demo=False, verbose=True): """ Runs ENERPI Sensor & Logger :param path_st: :param delta_sampling: :param roll_time: :param sampling_ms: :param timeout: :param is_demo: :param verbose: """ def _save_buffer(buffer, process_save, path_store, data_catalog, v): if process_save is not None and process_save.is_alive(): process_save.terminate() process_save = mp.Process(target=save_raw_data, args=(buffer, path_store, data_catalog, v), name='enerpi_save_buffer') process_save.start() return process_save global LED_STATE s_calc = sampling_ms if sampling_ms > 0 else 1 n_samples_buffer = int(round(roll_time * 1000 / s_calc)) intro = (INIT_LOG_MARK + '\n *** Calculating RMS values with window ' 'of {} frames (deltaT={} s, sampling: {} ms)' .format(n_samples_buffer, roll_time, sampling_ms)) log(intro, 'ok') data_generator = enerpi_sampler_rms( n_samples_buffer=n_samples_buffer, delta_sampling=delta_sampling, min_ts_ms=sampling_ms, use_dummy_sensors=is_demo, verbose=verbose) LED_STATE = 0 counter, p_save = 0, None led = get_rgbled(verbose=verbose) sock_send, counter_unreachable = None, np.array([0, 0]) catalog = init_catalog( sensors=SENSORS, raw_file=path_st, check_integrity=True, archive_existent=True) l_ini = [np.nan] * SENSORS.n_cols_sampling l_ini[0] = dt.datetime.now() buffer_disk = np.array(l_ini * N_SAMPLES_BUFFER_DISK).reshape( N_SAMPLES_BUFFER_DISK, SENSORS.n_cols_sampling) tic_abs = time() cond_while = True if timeout is None else TimerExiter(timeout) codec = get_codec() port = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) if n_samples_buffer is None: min_n_raw_samples = MIN_N_SAMPLES_ABS else: min_n_raw_samples = max( MIN_N_SAMPLES_ABS, int( MIN_N_SAMPLES_DELTA_FRACTION * min(MIN_N_SAMPLES_MAX_CONSIDERED, n_samples_buffer)) ) error_decay = {'counter_act': 0, 'subject': 'SAMPLING DECAY -> {}', 'mask': 'Sampling freq decay until {}. ' '# act: {}. # Unreach. Net: {}', 'last_error_decay': None} # Loop try: while cond_while: # Recibe sample del generador de datos data = next(data_generator) # Broadcast mensaje sock_send = broadcast_msg( tuple_to_dict_json(data), counter_unreachable, sock_send=sock_send, verbose=verbose, codec=codec, port=port) # Almacenamiento en buffer for i in range(len(data)): buffer_disk[counter, i] = data[i] counter += 1 if (data[-2] < MIN_N_SAMPLES_ABS) \ or (data[-2] < min_n_raw_samples) and (LED_STATE == 0): # Sampling decay problem --> red blink (ERROR SAMPLING) _set_led_state_alarm( led, time_blinking=10, timeout=10, time_on=.1, alarm_type='error') error_decay['counter_act'] += 1 if ((error_decay['counter_act'] > 5) and ((error_decay['last_error_decay'] is None) or (time() - error_decay['last_error_decay'] > 300))): # Decay error update error_decay['last_error_decay'] = time() msg = error_decay['mask'].format( data[-2], error_decay['counter_act'], counter_unreachable) _ = push_enerpi_error( error_decay['subject'].format(data[-2]), msg) error_decay['counter_act'] = 0 elif (counter_unreachable[0] > 1) and (LED_STATE == 0): # Unreachable network (wifi issues) --> 2x yellow blink (ERROR NETWORK) _set_led_state_alarm(led, time_blinking=2, time_on=.2, timeout=2, alarm_type='warning') elif (LED_STATE == 0) and (counter % 2 == 0): # Normal operation: blink with color as function of main_rms value in W --> LED Blink every 2 sec _set_led_blink_rgbled(led, data[1]) elif LED_STATE == 0: # Reset decay error with normal operation error_decay['counter_act'] = 0 # Almacenamiento en disco del buffer if counter >= N_SAMPLES_BUFFER_DISK: # Compactado de HDF Store cada STORE_PERIODIC_CATALOG_SEC w_compact = time() - tic_abs >= STORE_PERIODIC_CATALOG_SEC if w_compact: p_save = _save_buffer(buffer_disk, p_save, path_st, catalog, verbose) else: p_save = _save_buffer(buffer_disk, p_save, path_st, None, verbose) if w_compact: tic_abs = time() # 2x blink azul en grabación _set_led_state_info(led, n_blinks=2) buffer_disk[:, 1] = np.nan counter = 0 except StopIteration: log('Exiting SENDER because StopIteration', 'warn', verbose) except KeyboardInterrupt: # log('Interrumpting SENDER with KeyboardInterrupt', 'warn', verbose) pass [obj.close() for obj in [sock_send, led] if obj is not None] if is_demo: log('Exiting SENDER_RANDOM...', 'info', verbose) else: log('Exiting ENERPI_LOGGER...', 'info', verbose)
# -*- 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,
# -*- coding: utf-8 -*- """ ENERPI - RGB LED control methods """ 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
# -*- coding: utf-8 -*- """ ENERPI - RGB LED control methods """ 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
# -*- 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'))
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): """
""" ENERPIWEB - CLI methods: - 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} * * * * ...'
import os 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.)))
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')
def enerpi_logger(path_st=HDF_STORE_PATH, delta_sampling=SENSORS.delta_sec_data, roll_time=SENSORS.rms_roll_window_sec, sampling_ms=SENSORS.ts_data_ms, timeout=None, is_demo=False, verbose=True): """ Runs ENERPI Sensor & Logger :param path_st: :param delta_sampling: :param roll_time: :param sampling_ms: :param timeout: :param is_demo: :param verbose: """ def _save_buffer(buffer, process_save, path_store, data_catalog, v): if process_save is not None and process_save.is_alive(): process_save.terminate() process_save = mp.Process(target=save_raw_data, args=(buffer, path_store, data_catalog, v), name='enerpi_save_buffer') process_save.start() return process_save global LED_STATE s_calc = sampling_ms if sampling_ms > 0 else 1 n_samples_buffer = int(round(roll_time * 1000 / s_calc)) intro = (INIT_LOG_MARK + '\n *** Calculating RMS values with window ' 'of {} frames (deltaT={} s, sampling: {} ms)'.format( n_samples_buffer, roll_time, sampling_ms)) log(intro, 'ok') data_generator = enerpi_sampler_rms(n_samples_buffer=n_samples_buffer, delta_sampling=delta_sampling, min_ts_ms=sampling_ms, use_dummy_sensors=is_demo, verbose=verbose) LED_STATE = 0 counter, p_save = 0, None led = get_rgbled(verbose=verbose) sock_send, counter_unreachable = None, np.array([0, 0]) catalog = init_catalog(sensors=SENSORS, raw_file=path_st, check_integrity=True, archive_existent=True) l_ini = [np.nan] * SENSORS.n_cols_sampling l_ini[0] = dt.datetime.now() buffer_disk = np.array(l_ini * N_SAMPLES_BUFFER_DISK).reshape( N_SAMPLES_BUFFER_DISK, SENSORS.n_cols_sampling) tic_abs = time() cond_while = True if timeout is None else TimerExiter(timeout) codec = get_codec() port = CONFIG.getint('BROADCAST', 'UDP_PORT', fallback=57775) if n_samples_buffer is None: min_n_raw_samples = MIN_N_SAMPLES_ABS else: min_n_raw_samples = max( MIN_N_SAMPLES_ABS, int(MIN_N_SAMPLES_DELTA_FRACTION * min(MIN_N_SAMPLES_MAX_CONSIDERED, n_samples_buffer))) error_decay = { 'counter_act': 0, 'subject': 'SAMPLING DECAY -> {}', 'mask': 'Sampling freq decay until {}. ' '# act: {}. # Unreach. Net: {}', 'last_error_decay': None } # Loop try: while cond_while: # Recibe sample del generador de datos data = next(data_generator) # Broadcast mensaje sock_send = broadcast_msg(tuple_to_dict_json(data), counter_unreachable, sock_send=sock_send, verbose=verbose, codec=codec, port=port) # Almacenamiento en buffer for i in range(len(data)): buffer_disk[counter, i] = data[i] counter += 1 if (data[-2] < MIN_N_SAMPLES_ABS) \ or (data[-2] < min_n_raw_samples) and (LED_STATE == 0): # Sampling decay problem --> red blink (ERROR SAMPLING) _set_led_state_alarm(led, time_blinking=10, timeout=10, time_on=.1, alarm_type='error') error_decay['counter_act'] += 1 if ((error_decay['counter_act'] > 5) and ((error_decay['last_error_decay'] is None) or (time() - error_decay['last_error_decay'] > 300))): # Decay error update error_decay['last_error_decay'] = time() msg = error_decay['mask'].format( data[-2], error_decay['counter_act'], counter_unreachable) _ = push_enerpi_error( error_decay['subject'].format(data[-2]), msg) error_decay['counter_act'] = 0 elif (counter_unreachable[0] > 1) and (LED_STATE == 0): # Unreachable network (wifi issues) --> 2x yellow blink (ERROR NETWORK) _set_led_state_alarm(led, time_blinking=2, time_on=.2, timeout=2, alarm_type='warning') elif (LED_STATE == 0) and (counter % 2 == 0): # Normal operation: blink with color as function of main_rms value in W --> LED Blink every 2 sec _set_led_blink_rgbled(led, data[1]) elif LED_STATE == 0: # Reset decay error with normal operation error_decay['counter_act'] = 0 # Almacenamiento en disco del buffer if counter >= N_SAMPLES_BUFFER_DISK: # Compactado de HDF Store cada STORE_PERIODIC_CATALOG_SEC w_compact = time() - tic_abs >= STORE_PERIODIC_CATALOG_SEC if w_compact: p_save = _save_buffer(buffer_disk, p_save, path_st, catalog, verbose) else: p_save = _save_buffer(buffer_disk, p_save, path_st, None, verbose) if w_compact: tic_abs = time() # 2x blink azul en grabación _set_led_state_info(led, n_blinks=2) buffer_disk[:, 1] = np.nan counter = 0 except StopIteration: log('Exiting SENDER because StopIteration', 'warn', verbose) except KeyboardInterrupt: # log('Interrumpting SENDER with KeyboardInterrupt', 'warn', verbose) pass [obj.close() for obj in [sock_send, led] if obj is not None] if is_demo: log('Exiting SENDER_RANDOM...', 'info', verbose) else: log('Exiting ENERPI_LOGGER...', 'info', verbose)
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)
""" ENERPIWEB - CLI methods: - 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
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)