def test_logger_destination_error(self): """ Test Error gets returned when destination isn't 0 or 1 :assert: Assert ValueError is returned when destination=2 """ with pytest.raises(ValueError) as error_exec: logger.setup(__name__, destination=2) assert "ValueError: Invalid destination 2" in str(error_exec)
def __init__(self, _storage): self._storage = _storage if not Restore._logger: Restore._logger = logger.setup(self._MODULE_NAME, destination=_LOGGER_DESTINATION, level=_LOGGER_LEVEL)
def __init__(self): super().__init__() if not self._logger: self._logger = logger.setup(self._MODULE_NAME, destination=_LOGGER_DESTINATION, level=_LOGGER_LEVEL) # Handled Restore command line parameters try: self._backup_id = Parser.get('--backup-id') self._file_name = Parser.get('--file') except Exception as _ex: _message = _MESSAGES_LIST["e000003"].format(_ex) _logger.exception(_message) raise exceptions.ArgumentParserError(_message) self._restore_lib = lib.BackupRestoreLib(self._storage_async, self._logger) self._job = lib.Job() self._force_restore = True """ Restore a backup doesn't exist in the backups table """ # Creates the objects references used by the library lib._logger = self._logger lib._storage = self._storage_async
def test_destination_console(self): """ Test the logger type being returned when destination=1 :assert: Assert that the setup returns instance of type logging.Logger """ instance = logger.setup(__name__, destination=1) assert isinstance(instance, logging.Logger) is True
def __init__(self, _storage): self._storage = _storage if not Backup._logger: Backup._logger = logger.setup(self._MODULE_NAME, destination=_LOGGER_DESTINATION, level=_LOGGER_LEVEL) self._backup_lib = lib.BackupRestoreLib(self._storage, self._logger) self.STORAGE_TABLE_BACKUPS = self._backup_lib.STORAGE_TABLE_BACKUPS
def test_logger_level(self): """ Test logger level gets updated :assert: Assert that unless i==0, output.getEffectiveLevel() == i """ for i in range(0, 60, 10): output = logger.setup(__name__, level=i) if i == 0: # Level NOTSET (0) so inherits level WARNING (30) assert logging.WARNING == output.getEffectiveLevel() else: assert i == output.getEffectiveLevel()
def test_logger_instance(self): """ Test the logger type being returned at setup :assert: Assert that setup returns instance of type logger.Logger Assert instance name Assert instance hasHandler Assert instance default log level WARNING """ instance = logger.setup(__name__) assert isinstance(instance, logging.Logger) assert "test_logger" == instance.name assert instance.hasHandlers() assert logging.WARNING == instance.getEffectiveLevel()
def __init__(self): self._logger = logger.setup(__name__) self._monitor_loop_task = None # type: asyncio.Task """Task for :meth:`_monitor_loop`, to ensure it has finished""" self._sleep_interval = None # type: int """The time (in seconds) to sleep between health checks""" self._ping_timeout = None # type: int """Timeout for a response from any given micro-service""" self._max_attempts = None # type: int """Number of max attempts for finding a heartbeat of service""" self._restart_failed = None # type: str """Restart failed microservice - manual/auto""" self.restarted_services = []
def test_compare_setup(self): """ Test that logger.setup() generates the same value as logging for level - 10 to 50 propagate: True or False :assert: Assert logging.getLogger() and logger.setup return the same value(s) """ for name in (__name__, 'aaa'): log = logging.getLogger(name) for level in range(10, 60, 10): for propagate in (True, False): log.setLevel(level) log.propagate = propagate assert log is logger.setup( name, propagate=propagate, level=level)
def __init__(self): super().__init__() if not self._logger: self._logger = logger.setup(self._MODULE_NAME, destination=_LOGGER_DESTINATION, level=_LOGGER_LEVEL) self._backup = Backup(self._storage_async) self._backup_lib = lib.BackupRestoreLib(self._storage_async, self._logger) self._job = lib.Job() # Creates the objects references used by the library lib._logger = self._logger lib._storage = self._storage_async
async def run(self): global _log_performance global _LOGGER # Setups signals handlers, to properly handle the termination # a) SIGTERM - 15 : kill or system shutdown signal.signal(signal.SIGTERM, SendingProcess._signal_handler) # Command line parameter handling self._log_performance, self._debug_level = handling_input_parameters() _log_performance = self._log_performance try: self._storage_async = StorageClientAsync(self._core_management_host, self._core_management_port) self._readings = ReadingsStorageClientAsync(self._core_management_host, self._core_management_port) self._audit = AuditLogger(self._storage_async) except Exception as ex: SendingProcess._logger.exception(_MESSAGES_LIST["e000023"].format(str(ex))) sys.exit(1) else: SendingProcess._logger.removeHandler(SendingProcess._logger.handle) logger_name = _MODULE_NAME + "_" + self._name SendingProcess._logger = logger.setup(logger_name, level=logging.INFO if self._debug_level in [None, 0, 1] else logging.DEBUG) _LOGGER = SendingProcess._logger try: is_started = await self._start() if is_started: await self.send_data() self.stop() SendingProcess._logger.info("Execution completed.") sys.exit(0) except (ValueError, Exception) as ex: SendingProcess._logger.exception(_MESSAGES_LIST["e000002"].format(str(ex))) sys.exit(1)
# FLEDGE_END """Common FledgeProcess Class""" from abc import ABC, abstractmethod import argparse import time from fledge.common.storage_client.storage_client import StorageClientAsync, ReadingsStorageClientAsync from fledge.common import logger from fledge.common.microservice_management_client.microservice_management_client import MicroserviceManagementClient __author__ = "Ashwin Gopalakrishnan, Amarendra K Sinha" __copyright__ = "Copyright (c) 2017 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _logger = logger.setup(__name__) class ArgumentParserError(Exception): """ Override default exception to not terminate application """ def __init__(self, message): self.message = message def __str__(self): fmt = '%(message)s' return fmt % dict(message=self.message) class SilentArgParse(argparse.ArgumentParser): def error(self, message): """ Override default error functionality to not terminate application """
from fledge.common.plugin_discovery import PluginDiscovery from fledge.services.core.api.plugins import common from fledge.common.configuration_manager import ConfigurationManager from fledge.common.audit_logger import AuditLogger __author__ = "Ashish Jabble" __copyright__ = "Copyright (c) 2019, Dianomic Systems Inc." __license__ = "Apache 2.0" __version__ = "${VERSION}" _help = """ ------------------------------------------------------------------------------- | PUT | /fledge/plugin/{type}/{name}/update | ------------------------------------------------------------------------------- """ _logger = logger.setup(__name__, level=logging.INFO) async def update_plugin(request: web.Request) -> web.Response: """ update plugin :Example: curl -sX PUT http://localhost:8081/fledge/plugins/south/sinusoid/update curl -sX PUT http://localhost:8081/fledge/plugins/north/http_north/update curl -sX PUT http://localhost:8081/fledge/plugins/filter/metadata/update curl -sX PUT http://localhost:8081/fledge/plugins/notificationDelivery/asset/update curl -sX PUT http://localhost:8081/fledge/plugins/notificationRule/OutOfBound/update """ _type = request.match_info.get('type', None) name = request.match_info.get('name', None) try:
def plugin_init(data): """ Initializes the OMF plugin for the sending of blocks of readings to the PI Connector. Args: Returns: Raises: PluginInitializeFailed """ global _config global _config_omf_types global _logger global _recreate_omf_objects global _log_debug_level, _log_performance, _stream_id _log_debug_level = data['debug_level'] _log_performance = data['log_performance'] _stream_id = data['stream_id'] try: # note : _module_name is used as __name__ refers to the Sending Process logger_name = _MODULE_NAME + "_" + str(_stream_id) _logger = \ logger.setup(logger_name, destination=_LOGGER_DESTINATION) if _log_debug_level == 0 else\ logger.setup( logger_name, destination=_LOGGER_DESTINATION, level=logging.INFO if _log_debug_level == 1 else logging.DEBUG) except Exception as ex: _logger.error("{0} - ERROR - {1}".format( time.strftime("%Y-%m-%d %H:%M:%S:"), plugin_common.MESSAGES_LIST["e000012"].format(str(ex)))) raise ex _logger.debug("{0} - ".format("plugin_info")) _validate_configuration(data) # Retrieves the configurations and apply the related conversions _config['_CONFIG_CATEGORY_NAME'] = data['_CONFIG_CATEGORY_NAME'] _config['namespace'] = data['namespace']['value'] _config['tenant_id'] = data['tenant_id']['value'] _config['client_id'] = data['client_id']['value'] _config['client_secret'] = data['client_secret']['value'] _config['URL'] = data['URL']['value'] # Replaces placeholders if the URL doesn't already contain the final address _config['URL'] = _config['URL'].replace("TENANT_ID_PLACEHOLDER", _config['tenant_id']) _config['URL'] = _config['URL'].replace("NAMESPACE_ID_PLACEHOLDER", _config['namespace']) _config['producerToken'] = data['producerToken']['value'] _config['OMFMaxRetry'] = int(data['OMFMaxRetry']['value']) _config['OMFRetrySleepTime'] = int(data['OMFRetrySleepTime']['value']) _config['OMFHttpTimeout'] = int(data['OMFHttpTimeout']['value']) _config['StaticData'] = ast.literal_eval(data['StaticData']['value']) _config['formatNumber'] = data['formatNumber']['value'] _config['formatInteger'] = data['formatInteger']['value'] _config['notBlockingErrors'] = ast.literal_eval(data['notBlockingErrors']['value']) _config['compression'] = data['compression']['value'] # TODO: compare instance fetching via inspect vs as param passing # import inspect # _config['sending_process_instance'] = inspect.currentframe().f_back.f_locals['self'] _config['sending_process_instance'] = data['sending_process_instance'] # _config_omf_types = json.loads(data['omf_types']['value']) # noinspection PyProtectedMember _config_omf_types = _config['sending_process_instance']._fetch_configuration( cat_name=_CONFIG_CATEGORY_OMF_TYPES_NAME, cat_desc=_CONFIG_CATEGORY_OMF_TYPES_DESCRIPTION, cat_config=_CONFIG_DEFAULT_OMF_TYPES, cat_keep_original=True) _validate_configuration_omf_type(_config_omf_types) # Converts the value field from str to a dict for item in _config_omf_types: if _config_omf_types[item]['type'] == 'JSON': # The conversion from a dict to str changes the case and it should be fixed before the conversion value = _config_omf_types[item]['value'].replace("true", "True") new_value = ast.literal_eval(value) _config_omf_types[item]['value'] = new_value _logger.debug("{0} - URL {1}".format("plugin_init", _config['URL'])) try: _recreate_omf_objects = True except Exception as ex: _logger.error(plugin_common.MESSAGES_LIST["e000011"].format(ex)) raise plugin_exceptions.PluginInitializeFailed(ex) return _config
def __init__(self): super().__init__() self._logger = logger.setup("Data Purge") self._audit = AuditLogger(self._storage_async)
class ServiceRegistry: _registry = list() # INFO - level 20 _logger = logger.setup(__name__, level=20) @classmethod def register(cls, name, s_type, address, port, management_port, protocol='http'): """ registers the service instance :param name: name of the service :param s_type: a valid service type; e.g. Storage, Core, Southbound :param address: any IP or host address :param port: a valid positive integer :param management_port: a valid positive integer for management operations e.g. ping, shutdown :param protocol: defaults to http :return: registered services' uuid """ new_service = True try: current_service = cls.get(name=name) except service_registry_exceptions.DoesNotExist: pass else: # Re: FOGL-1123 if current_service[0]._status in [ ServiceRecord.Status.Running, ServiceRecord.Status.Unresponsive ]: raise service_registry_exceptions.AlreadyExistsWithTheSameName else: new_service = False current_service_id = current_service[0]._id if port is not None and cls.check_address_and_port(address, port): raise service_registry_exceptions.AlreadyExistsWithTheSameAddressAndPort if cls.check_address_and_mgt_port(address, management_port): raise service_registry_exceptions.AlreadyExistsWithTheSameAddressAndManagementPort if port is not None and (not isinstance(port, int)): raise service_registry_exceptions.NonNumericPortError if not isinstance(management_port, int): raise service_registry_exceptions.NonNumericPortError if new_service is False: # Remove current service to enable the service to register with new management port etc cls.remove_from_registry(current_service_id) service_id = str( uuid.uuid4()) if new_service is True else current_service_id registered_service = ServiceRecord(service_id, name, s_type, protocol, address, port, management_port) cls._registry.append(registered_service) cls._logger.info("Registered {}".format(str(registered_service))) return service_id @classmethod def _expunge(cls, service_id, service_status): """ removes the service instance from action :param service_id: a uuid of registered service :param service_status: service status to be marked :return: service_id on successful deregistration """ services = cls.get(idx=service_id) service_name = services[0]._name services[0]._status = service_status cls._remove_from_scheduler_records(service_name) # Remove interest registry records, if any interest_recs = InterestRegistry().get(microservice_uuid=service_id) for interest_rec in interest_recs: InterestRegistry().unregister(interest_rec._registration_id) return services[0] @classmethod def unregister(cls, service_id): """ deregisters the service instance :param service_id: a uuid of registered service :return: service_id on successful deregistration """ expunged_service = cls._expunge(service_id, ServiceRecord.Status.Shutdown) cls._logger.info("Stopped {}".format(str(expunged_service))) return service_id @classmethod def mark_as_failed(cls, service_id): """ marks the service instance as failed :param service_id: a uuid of registered service :return: service_id on successful deregistration """ expunged_service = cls._expunge(service_id, ServiceRecord.Status.Failed) cls._logger.info("Mark as failed {}".format(str(expunged_service))) return service_id @classmethod def remove_from_registry(cls, service_id): """ remove service_id from service_registry. :param service_id: a uuid of registered service """ services = cls.get(idx=service_id) cls._registry.remove(services[0]) @classmethod def _remove_from_scheduler_records(cls, service_name): """ removes service aka STARTUP from Scheduler internal records :param service_name :return: """ if service_name in ("Fledge Storage", "Fledge Core"): return # Require a local import in order to avoid circular import references from fledge.services.core import server if server.Server.scheduler is None: return asyncio.ensure_future( server.Server.scheduler.remove_service_from_task_processes( service_name)) @classmethod def all(cls): return cls._registry @classmethod def filter(cls, **kwargs): # OR based filter services = cls._registry for k, v in kwargs.items(): if v: services = [ s for s in cls._registry if getattr(s, k, None) == v ] return services @classmethod def get(cls, idx=None, name=None, s_type=None): services = cls.filter(_id=idx, _name=name, _type=s_type) if len(services) == 0: raise service_registry_exceptions.DoesNotExist return services @classmethod def check_address_and_port(cls, address, port): # AND based check # ugly hack! <Make filter to support AND | OR> services = [ s for s in cls._registry if getattr(s, "_address") == address and getattr(s, "_port") == port and getattr(s, "_status") != ServiceRecord.Status.Failed ] if len(services) == 0: return False return True @classmethod def check_address_and_mgt_port(cls, address, m_port): # AND based check # ugly hack! <Make filter to support AND | OR> services = [ s for s in cls._registry if getattr(s, "_address") == address and getattr(s, "_management_port") == m_port and getattr(s, "_status") != ServiceRecord.Status.Failed ] if len(services) == 0: return False return True @classmethod def filter_by_name_and_type(cls, name, s_type): # AND based check # ugly hack! <Make filter to support AND | OR> services = [ s for s in cls._registry if getattr(s, "_name") == name and getattr(s, "_type") == s_type ] if len(services) == 0: raise service_registry_exceptions.DoesNotExist return services
""" Common class for TI SensorTag CC2650 plugins """ import pexpect from pexpect import ExceptionPexpect, EOF, TIMEOUT import time import re from fledge.common import logger __author__ = "Amarendra K Sinha" __copyright__ = "Copyright (c) 2018 Dianomic Systems" __license__ = "Apache 2.0" __version__ = "${VERSION}" _LOGGER = logger.setup(__name__, level=20) # TODO: Out of 14 services, only below 5 services have been attended to. Next tasks will take care of at least up/down + # tick and battery level indicator services. Also, implement a ping method. characteristics = { 'temperature': { 'data': { 'uuid': 'f000aa01-0451-4000-b000-000000000000', 'handle': '0x0000' }, 'configuration': { 'uuid': 'f000aa02-0451-4000-b000-000000000000', 'handle': '0x0000' }, 'period': { 'uuid': 'f000aa03-0451-4000-b000-000000000000',
from fledge.common.common import _FLEDGE_ROOT from fledge.services.core.api.plugins import common __author__ = "Amarendra K Sinha" __copyright__ = "Copyright (c) 2018 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _help = """ ------------------------------------------------------------------------------- | POST | /fledge/scheduled/task | | DELETE | /fledge/scheduled/task/{task_name} | ------------------------------------------------------------------------------- """ _logger = logger.setup() async def add_task(request): """ Create a new task to run a specific plugin :Example: curl -X POST http://localhost:8081/fledge/scheduled/task -d '{ "name": "North Readings to PI", "plugin": "pi_server", "type": "north", "schedule_type": 3, "schedule_day": 0, "schedule_time": 0, "schedule_repeat": 30,
import asyncio import datetime import time from typing import List, Union import json from fledge.common import logger from fledge.common import statistics from fledge.common.storage_client.exceptions import StorageServerError __author__ = "Terris Linenbach, Amarendra K Sinha" __copyright__ = "Copyright (c) 2017 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _LOGGER = logger.setup(__name__) # type: logging.Logger _MAX_ATTEMPTS = 2 # _LOGGER = logger.setup(__name__, level=logging.DEBUG) # type: logging.Logger # _LOGGER = logger.setup(__name__, destination=logger.CONSOLE, level=logging.DEBUG) class Ingest(object): """Adds sensor readings to Fledge Also tracks readings-related statistics. Readings are added to a configurable list. Configurable batches of inserts are sent to storage """ # Class attributes
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # FLEDGE_BEGIN # See: http://fledge.readthedocs.io/ # FLEDGE_END """Purge process starter""" import asyncio from fledge.tasks.purge.purge import Purge from fledge.common import logger __author__ = "Terris Linenbach, Vaibhav Singhal" __copyright__ = "Copyright (c) 2017 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" if __name__ == '__main__': _logger = logger.setup("Purge") loop = asyncio.get_event_loop() purge_process = Purge() loop.run_until_complete(purge_process.run())
# See: http://fledge.readthedocs.io/ # FLEDGE_END """Common Utilities""" import aiohttp import asyncio from fledge.common import logger __author__ = "Amarendra Kumar Sinha" __copyright__ = "Copyright (c) 2017 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _logger = logger.setup(__name__, level=20) _MAX_ATTEMPTS = 15 """Number of max attempts for finding a heartbeat of service""" async def ping_service(service, loop=None): attempt_count = 1 """Number of current attempt to ping url""" loop = asyncio.get_event_loop() if loop is None else loop url_ping = "{}://{}:{}/fledge/service/ping".format(service._protocol, service._address, service._management_port) async with aiohttp.ClientSession(loop=loop) as session: while attempt_count < _MAX_ATTEMPTS + 1:
# FLEDGE_BEGIN # See: http://fledge.readthedocs.io/ # FLEDGE_END """shim layer between Python and C++""" import os import importlib.util import sys import json import logging from fledge.common import logger from fledge.common.common import _FLEDGE_ROOT from fledge.services.core.api.plugins import common _LOGGER = logger.setup(__name__, level=logging.WARN) _plugin = None _LOGGER.debug( "Loading shim layer for python plugin '{}', type 'filter' ".format( sys.argv[1])) def _plugin_obj(): global _plugin plugin = sys.argv[1] plugin_type = "filter" plugin_module_path = "{}/python/fledge/plugins/filter/{}".format( _FLEDGE_ROOT, plugin) _plugin = common.load_python_plugin(plugin_module_path, plugin, plugin_type)
import json import asyncio import sys from fledge.services.south import exceptions from fledge.common import logger from fledge.services.south.ingest import Ingest from fledge.services.common.microservice import FledgeMicroservice from aiohttp import web __author__ = "Terris Linenbach, Amarendra K Sinha, Ashish Jabble" __copyright__ = "Copyright (c) 2017 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _LOGGER = logger.setup(__name__) _MAX_RETRY_POLL = 3 _TIME_TO_WAIT_BEFORE_RETRY = 1 _CLEAR_PENDING_TASKS_TIMEOUT = 3 class Server(FledgeMicroservice): """" Implements the South Microservice """ _DEFAULT_CONFIG = { } # South Server configuration which will get updated with process configuration from DB. _PLUGIN_MODULE_PATH = "fledge.plugins.south" _MESSAGES_LIST = { # Information messages
_message = _MESSAGES_LIST["e000002"].format(_ex) _logger.error(_message) self.shutdown() raise exceptions.RestoreFailed(_message) else: self.shutdown() if __name__ == "__main__": # Initializes the logger try: _logger = logger.setup(_MODULE_NAME, destination=_LOGGER_DESTINATION, level=_LOGGER_LEVEL) except Exception as ex: message = _MESSAGES_LIST["e000001"].format(str(ex)) current_time = time.strftime("%Y-%m-%d %H:%M:%S") print("[FLEDGE] {0} - ERROR - {1}".format(current_time, message), file=sys.stderr) sys.exit(1) # Starts _logger.info(_MESSAGES_LIST["i000001"]) # Initializes FledgeProcess and Backup classes - handling the command line parameters try: backup_process = BackupProcess()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # FLEDGE_BEGIN # See: http://fledge.readthedocs.io/ # FLEDGE_END """Statistics history process starter""" import asyncio from fledge.tasks.statistics.statistics_history import StatisticsHistory from fledge.common import logger __author__ = "Terris Linenbach, Vaibhav Singhal" __copyright__ = "Copyright (c) 2017 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" if __name__ == '__main__': _logger = logger.setup("StatisticsHistory") statistics_history_process = StatisticsHistory() loop = asyncio.get_event_loop() loop.run_until_complete(statistics_history_process.run())
cls._pid_file_create(full_path, pid) @classmethod def set_as_completed(cls, file_name): """ Sets a job as completed Args: file_name: semaphore file either for backup or restore operations Returns: Raises: """ _logger.debug("{func}".format(func="set_as_completed")) full_path = JOB_SEM_FILE_PATH + "/" + file_name if os.path.exists(full_path): os.remove(full_path) if __name__ == "__main__": message = _MESSAGES_LIST["e000003"] print(message) if False: # Used to assign the proper objects type without actually executing them _storage = StorageClientAsync("127.0.0.1", "0") _logger = logger.setup(_MODULE_NAME)
from fledge.services.core.api.plugins import common __author__ = "Massimiliano Pinto, Amarendra K Sinha" __copyright__ = "Copyright (c) 2018 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _help = """ --------------------------------------------------------------------------- | POST GET | /fledge/filter | | PUT GET DELETE | /fledge/filter/{user_name}/pipeline | | GET DELETE | /fledge/filter/{filter_name} | --------------------------------------------------------------------------- """ _LOGGER = logger.setup("filter") async def create_filter(request: web.Request) -> web.Response: """ Create a new filter with a specific plugin :Example: curl -X POST http://localhost:8081/fledge/filter -d '{"name": "North_Readings_to_PI_scale_stage_1Filter", "plugin": "scale"}' curl -X POST http://localhost:8081/fledge/filter -d '{"name": "North_Readings_to_PI_scale_stage_1Filter", "plugin": "scale", "filter_config": {"offset":"1","enable":"true"}}' 'name' is the filter name 'plugin' is the filter plugin name 'filter_config' is the new configuration of the plugin, part or full, should we desire to modify the config at creation time itself
def __init__(self): """Initialise the JQFilter""" self._logger = logger.setup("JQFilter")
# FLEDGE_BEGIN # See: http://fledge.readthedocs.io/ # FLEDGE_END """ Module for Enviro pHAT 'poll' type plugin """ import copy import logging import serial import time from fledge.common import logger from fledge.plugins.common import utils _LOGGER = logger.setup(__name__, level=logging.INFO) try: from envirophat import light, weather, motion # unused: analog except FileNotFoundError: _LOGGER.error("Ensure i2c is enabled on the Pi and other dependencies are installed correctly!") __author__ = "Ashwin Gopalakrishnan, Amarendra K Sinha" __copyright__ = "Copyright (c) 2018 Dianomic Systems" __license__ = "Apache 2.0" __version__ = "${VERSION}" _DEFAULT_CONFIG = { 'plugin': { 'description': 'Enviro pHAT Poll Plugin', 'type': 'string',
# -*- coding: utf-8 -*- # FLEDGE_BEGIN # See: http://fledge.readthedocs.io/ # FLEDGE_END """ Fledge package updater API support""" from aiohttp import web import datetime from fledge.services.core import server from fledge.common import logger from fledge.services.core.scheduler.entities import ManualSchedule _LOG_LEVEL = 20 _logger = logger.setup(__name__, level=_LOG_LEVEL) __author__ = "Massimiliano Pinto" __copyright__ = "Copyright (c) 2018 OSIsoft, LLC" __license__ = "Apache 2.0" __version__ = "${VERSION}" _help = """ ----------------------------------------- | PUT | /fledge/update | ----------------------------------------- """ ### # The update.py is part of the Fledge REST API: # when called via PUT /fledge/update it will add/fetch the "manual update task"