コード例 #1
0
def initialize_app(flask_app):
    """Apply application configuration.

    Load configuration to Flask object and apply configuration to it
        :param flask_app: Flask application to configure
        :type flask_app: Flask
    """
    configure_app(flask_app)

    # Fix to handle properly X-Forwarded-Proto header
    # from werkzeug.contrib.fixers import ProxyFix
    flask_app.wsgi_app = ProxyFix(flask_app.wsgi_app)

    # Define base_url for the app
    blueprint = Blueprint('api', __name__, url_prefix=settings.API["base_url"])
    api.init_app(blueprint)
    api.add_namespace(admin_ns)
    api.add_namespace(sensors_ns)
    api.add_namespace(phone_ns)

    # Define base_url from swaggerui resources (js, css...)
    api_doc = flask_restx.apidoc.apidoc
    api_doc.url_prefix = settings.API["base_url"] + "/doc"

    flask_app.register_blueprint(blueprint)
コード例 #2
0
    def get(self, env):
        """
        Get current recording session.

        Get informations about the current recording session
            :param env: Environement identifier
            :type env: string
        """
        self.logger.info("GET env=%s", env)

        args = PARSER.parse_args(request)
        time = args.get('time', None)

        svc = RecorderService()
        try:
            result = svc.load_session(env, time)
            self.logger.debug(result)
        except RecordingException as exc:
            api.abort(exc.http_status, exc.message)
        return result
コード例 #3
0
    def post(self, env):
        """
        Start a session.

        Start a data recording session
            :param env: Environement identifier
            :type env: string
        """
        data = request.json
        self.logger.info("POST env=%s scenario=%s step=%s", env,
                         data.get("scenario"), data.get("step"))

        svc = RecorderService()
        try:
            result = svc.store_session(env, data.get("scenario"),
                                       data.get("step"))
        except RecordingException as exc:
            api.abort(exc.http_status, exc.message)

        return result
コード例 #4
0
    def delete(self, env):
        """
        Stop a session.

        Stop a data recording session
            :param env: Environement identifier
            :type env: string
        """
        self.logger.info("DELETE env=%s", env)

        svc = RecorderService()

        try:

            result = svc.load_session(env)
            svc.store_session(env, result.scenario, result.step, 0)
        except RecordingException as exc:
            api.abort(exc.http_status, exc.message)

        return result
コード例 #5
0
    def post(self, env):  # pylint: disable=no-self-use
        """
        Define current step.

        Define current step for a recording scenartion
            :param env: Environement identifier
            :type env: string
        """
        recorder = RecorderService()
        data = request.json

        self.logger.info("POST step env=%s step=%s", env, data.get("step"))

        try:

            result = recorder.load_session(env)

            result.step = data.get("step")
            recorder.store_session(env, result.scenario, result.step)
        except RecordingException as exc:
            api.abort(exc.http_status, exc.message)

        return result
コード例 #6
0
def initialize_app(flask_app):
    """Apply application configuration.

    Load configuration to Flask object and apply configuration to it
        :param flask_app: Flask application to configure
        :type flask_app: Flask
    """
    configure_app(flask_app)
    flask_app.wsgi_app = ProxyFix(flask_app.wsgi_app)

    blueprint = Blueprint('api',
                          __name__,
                          url_prefix=settings.API["context_root"])
    api.init_app(blueprint)

    api.add_namespace(equipements_namespace)
    #api.add_namespace(servers_namespace)
    api.add_namespace(recorder_namespace)
    api.add_namespace(monitoring_namespace)

    api_doc = flask_restx.apidoc.apidoc
    api_doc.url_prefix = settings.API["context_root"] + "/doc"
    flask_app.register_blueprint(blueprint)
    requests.urllib3.disable_warnings()
コード例 #7
0
import logging
import json
import urllib
import requests

from flask_restx import Resource
from flask import request
import settings
from api.datamodel import RUNNING_SCENARIO
from api.datamodel import STEP_POST, RECORDER_POST
from api.restx import API as api
from service.datamodel import RunningScenarioClass
from service.exception import RecordingException
from service.recorder import RecorderService

NS = api.namespace('recorders', description='Recording sessions management')

PARSER = api.parser()
PARSER.add_argument(
    'time',
    type=int,
    help='POSIX Timestamp (in nanosec) recorder started immediatly \
            before this time',
    default=None,
    location='args')


@NS.route('/environment/<string:env>')
@api.doc(params={'env': 'Environment identifier'})
class Recorder(Resource):
    """Recorder services management class."""
コード例 #8
0
ファイル: phone.py プロジェクト: zorglub42/marv2plage
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
"""FFBC8 weatherstation receive phone/browser data."""
import logging
import socket
import subprocess

from flask import request
from flask_restx import Resource
import requests
from api.restx import API

import settings
NS = API.namespace('phone', description='interact with phone')


@NS.route('/GPS')
class GPS(Resource):
    """Receive GPS data API Class."""

    logger = None

    # pylint: disable=keyword-arg-before-vararg
    def __init__(self, api=None, *args, **kwargs):
        Resource.__init__(self, api, kwargs)
        self.logger = logging.getLogger(__name__)

    def _send_influx(self, data):
        if data == "":
コード例 #9
0
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
"""FFBC8 weatherstation Admin API."""
import logging

from flask import request
from flask_restx import Resource

from api.datamodel import SYSTEM_COMMAND_PAYLOAD, SYSTEM_TIME,\
    WIFI_CONFIG_EXTENDED, WIFI_CONFIG
from api.restx import API
from services.admin import AdminService

NS = API.namespace('admin', description='Weather station admin')


@NS.route("/ping")
class Pinger(Resource):
    """System pingers."""

    logger = None

    # pylint: disable=keyword-arg-before-vararg
    def __init__(self, api=None, *args, **kwargs):
        Resource.__init__(self, api, kwargs)
        self.logger = logging.getLogger(__name__)

    def get(self):
        """Ping system."""
コード例 #10
0
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Zorglub42 {contact(at)zorglub42.fr}.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
"""FFBC8 weatherstation data model."""
from flask_restx import fields
from api.restx import API

# Model desecription for methods parameters
SYSTEM_COMMAND_PAYLOAD = API.model("systemCommand", {
    "command": fields.String(
        requied=True,
        description="Command to execute",
        enum=["shutdown", "reboot"]
    )
})
SYSTEM_TIME = API.model("dateTime", {
    "dateTime": fields.String(
        requied=True,
        description="Date is ISO format",
        example="2020-02-21T20:36:28Z"
    )
})

SENSOR_VALUE = API.model("sensorValue", {
    'name': fields.String(
        required=True,
        description='Sensor name',
コード例 #11
0
    def post(self, server):  # pylint: disable=locally-disabled,no-self-use
        """
        Power consumption receiver (see /equipments/{equipement}/measurements).

        Use instead /equipments/{equipement}/measurements with
        <code>[{"sensor": "power", "unit": "W", "value": power-value}]</code>
        as measurements payload<hr>

        Store a new power consumption measurement for a particular server
            :param server: Environement identifier
            :type server: string
        """

        data = request.json
        recorder_manager = RecorderService()

        self.log.info("POST server %s consumption %s in environment %s",
                      server, data.get("power"), data.get("environment"))

        time = data.get("time", None)
        try:
            recorder = recorder_manager.load_session(data.get("environment"),
                                                     time)
        except RecordingException as exc:
            if exc.http_status == 404:
                if settings.ALWAYS_RECORD:
                    recorder = RunningScenarioClass(data.get("environment"),
                                                    "n/s", "n/s")
            else:
                raise exc

        result = PowerMeasurementClass(recorder.environment, data.get("power"),
                                       recorder.scenario, recorder.step)

        influx_data = "PowerMeasurement,hardware="
        influx_data += server.replace(' ', '\\ ')
        influx_data += ",environment="
        influx_data += result.environment.replace(' ', '\\ ')
        influx_data += ",scenario="
        influx_data += result.scenario.replace(' ', '\\ ')
        influx_data += ",step="
        influx_data += result.step.replace(' ', '\\ ')
        influx_data += " power="
        influx_data += str(data.get("power"))
        if time is not None:
            influx_data = influx_data + " " + str(time)

        if settings.INFLUX["user"] is not None:
            auth = (settings.INFLUX["user"], settings.INFLUX["pass"])
        else:
            auth = None

        influx_url = settings.INFLUX["host"] + "/write?db="
        influx_url += settings.INFLUX["db"]
        response = requests.post(influx_url,
                                 data=influx_data,
                                 auth=auth,
                                 verify=False)
        if response.status_code != 204:
            log_msg = "Error while storing measurment: {}"
            log_msg = log_msg.format(response.text)
            api.abort(500, log_msg)

        influx_data = "SensorMeasurement,equipement="
        influx_data += server.replace(' ', '\\ ')
        influx_data += ",environment="
        influx_data += recorder.environment.replace(' ', '\\ ')
        influx_data += ",scenario="
        influx_data += recorder.scenario.replace(' ', '\\ ')
        influx_data += ",step="
        influx_data += recorder.step.replace(' ', '\\ ')
        influx_data += ",sensor=power"
        influx_data += ",unit=W"
        influx_data += " value="
        influx_data += str(data["power"])

        response = requests.post(influx_url,
                                 data=influx_data,
                                 auth=auth,
                                 verify=False)
        if response.status_code != 204:
            log_msg = "Error while storing measurment: {}"
            log_msg = log_msg.format(response.text)
            api.abort(500, log_msg)

        return result
コード例 #12
0
# 1.0.0 - 2017-02-20 : Release of the file
#
import logging
import requests

from flask import request
from flask_restx import Resource

import settings
from api.datamodel import POWER_MEASUREMENT, POWER_POST
from api.restx import API as api
from service.datamodel import PowerMeasurementClass, RunningScenarioClass
from service.exception import RecordingException
from service.recorder import RecorderService

NS = api.namespace('servers', description='Operations related to servers')


@NS.route('/<string:server>/consumption')
@NS.deprecated
class ServerConsumption(Resource):
    """Server consumption management API."""

    log = logging.getLogger(__name__)

    @api.expect(POWER_POST)
    @api.marshal_with(POWER_MEASUREMENT)
    def post(self, server):  # pylint: disable=locally-disabled,no-self-use
        """
        Power consumption receiver (see /equipments/{equipement}/measurements).
コード例 #13
0
ファイル: monitoring.py プロジェクト: bherard/energyrecorder
#
# Description :
#     API monitoring
# -------------------------------------------------------
# History     :
# 1.0.0 - 2017-05-11 : Release of the file
#

import logging

from flask_restx import Resource
from api.datamodel import API_STATUS
from api.restx import API as api
from service.monitoring import MonitoringService

NS = api.namespace('monitoring', description='API monitoring')


@NS.route('/ping')
class Ping(Resource):
    """API monitoring Ping class."""

    logger = logging.getLogger(__name__)

    @api.marshal_with(API_STATUS)
    def get(self):
        """Return API status."""
        self.logger.debug("GET ping")

        return MonitoringService().connect_influx()
コード例 #14
0
    def post(self, equipement):  # pylint: disable=locally-disabled,no-self-use
        """
        Measurements receiver.

        Store new measurements for a particular equipement
            :param equipement: Equipement identifier
            :type equipement: string
        """

        data = request.json
        recorder_manager = RecorderService()

        self.log.info("POST measurements for equiment %s in environment %s",
                      equipement, data.get("environment"))

        time = data.get("time", None)
        try:
            recorder = recorder_manager.load_session(data.get("environment"),
                                                     time)
        except RecordingException as exc:
            if exc.http_status == 404:
                if settings.ALWAYS_RECORD:
                    recorder = RunningScenarioClass(data.get("environment"),
                                                    "n/s", "n/s")
            else:
                raise exc

        result = APIStatusClass("OK")

        sm_influx_data = ""
        pm_influx_data = ""
        for measurement in data["measurements"]:
            time = measurement.get("time", None)

            if sm_influx_data != "":
                sm_influx_data += "\n"

            sm_influx_data += "SensorMeasurement,equipement="
            sm_influx_data += equipement.replace(' ', '\\ ')
            sm_influx_data += ",environment="
            sm_influx_data += recorder.environment.replace(' ', '\\ ')
            sm_influx_data += ",scenario="
            sm_influx_data += recorder.scenario.replace(' ', '\\ ')
            sm_influx_data += ",step="
            sm_influx_data += recorder.step.replace(' ', '\\ ')
            sm_influx_data += ",sensor="
            sm_influx_data += measurement["sensor"].replace(' ', '\\ ')
            sm_influx_data += ",unit="
            sm_influx_data += measurement["unit"].replace(' ', '\\ ')
            sm_influx_data += " value="
            sm_influx_data += str(measurement["value"])

            if time and time > 10e+9:
                #Introduce aleat of 0..9999 nano sec to avoid data mixup
                sm_time = time + random.randint(0, 9999)

                sm_influx_data = sm_influx_data + " " + str(sm_time)

            self._mqtt_svc.publish(recorder.environment, equipement,
                                   recorder.scenario, recorder.step,
                                   measurement["sensor"], measurement["unit"],
                                   measurement["value"], time)

            if measurement["sensor"] == "power":
                if pm_influx_data != "":
                    pm_influx_data += "\n"

                pm_influx_data = "PowerMeasurement,hardware="
                pm_influx_data += equipement.replace(' ', '\\ ')
                pm_influx_data += ",environment="
                pm_influx_data += recorder.environment.replace(' ', '\\ ')
                pm_influx_data += ",scenario="
                pm_influx_data += recorder.scenario.replace(' ', '\\ ')
                pm_influx_data += ",step="
                pm_influx_data += recorder.step.replace(' ', '\\ ')
                pm_influx_data += " power="
                pm_influx_data += str(measurement["value"])

        if settings.INFLUX["user"] is not None:
            auth = (settings.INFLUX["user"], settings.INFLUX["pass"])
        else:
            auth = None

        influx_url = settings.INFLUX["host"] + "/write?db="
        influx_url += settings.INFLUX["db"]
        response = requests.post(influx_url,
                                 data=sm_influx_data.encode("utf-8"),
                                 auth=auth,
                                 headers={
                                     "Content-Type":
                                     "application/x-www-form-urlencoded; " +
                                     "charset=UTF-8"
                                 },
                                 verify=False)
        if response.status_code != 204:
            log_msg = "Error while storing measurment: {}"
            log_msg = log_msg.format(response.text)
            api.abort(500, log_msg)

            response = requests.post(
                influx_url,
                data=pm_influx_data.encode("utf-8"),
                auth=auth,
                headers={
                    "Content-Type":
                    "application/x-www-form-urlencoded; " + "charset=UTF-8"
                },
                verify=False)
            if response.status_code != 204:
                log_msg = "Error while storing measurment: {}"
                log_msg = log_msg.format(response.text)
                api.abort(500, log_msg)

        self.log.info("POST measurements done!")

        return result
コード例 #15
0
import requests

from flask import request
from flask_restx import Resource
from service.mqtt import MQTTService

import settings
from api.datamodel import API_STATUS, MEASUREMENT_POST
from api.restx import API as api
from service.datamodel import APIStatusClass, RunningScenarioClass
from service.exception import RecordingException
from service.recorder import RecorderService
from service.mqtt import MQTTService

NS = api.namespace('equipments',
                   description='Equipements monitoring operations')


@NS.route('/<string:equipement>/measurements')
class EquipementMeasurements(Resource):
    """Server consumption management API."""

    log = logging.getLogger(__name__)

    def __init__(self, api=None, *args, **kwargs):
        super().__init__(api, *args, **kwargs)
        self._mqtt_svc = MQTTService()

    @api.expect(MEASUREMENT_POST)
    @api.marshal_with(API_STATUS)
    def post(self, equipement):  # pylint: disable=locally-disabled,no-self-use
コード例 #16
0
ファイル: datamodel.py プロジェクト: bherard/energyrecorder
# Description :
#     Public data model definitions
# -------------------------------------------------------
# History     :
# 1.0.0 - 2017-02-20 : Release of the file
#
from flask_restx import fields
from api.restx import API

# Model desecription for methods parameters
POWER_POST = API.model(
    'powerPost', {
        'power':
        fields.Integer(required=True,
                       description='Power consumption in Watts'),
        'time':
        fields.Integer(required=False, description='Measurment time stamp'),
        'environment':
        fields.String(required=True,
                      description='Recorder environment \
                                              identifier'),
    })
MEASUREMENT = API.model(
    "measurement", {
        'sensor':
        fields.String(required=True, description="Sensor/measurment name"),
        'unit':
        fields.String(required=True, description='Measurement unit'),
        'value':
        fields.Float(required=True, decription='Measurement value'),
        'time':
        fields.Integer(
コード例 #17
0
ファイル: sensors.py プロジェクト: zorglub42/marv2plage
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Zorglub42 {contact(at)zorglub42.fr}.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
"""FFBC8 weatherstation sensors API."""
import logging

from flask_restx import Resource, reqparse
from api.datamodel import (LAST_SENSORS_VALUES, GET_SENSOR_VALUES,
                           SENSOR_VALUES_TREND)
from api.restx import API
from services.sensors import SensorsService
NS = API.namespace('sensors', description='sensors resources')


@NS.route('/last')
class Last(Resource):
    """Last value for all sensors API Class."""

    logger = None

    # pylint: disable=keyword-arg-before-vararg
    def __init__(self, api=None, *args, **kwargs):
        Resource.__init__(self, api, kwargs)
        self.logger = logging.getLogger(__name__)

    @API.marshal_with(LAST_SENSORS_VALUES)
    def get(self):
コード例 #18
0
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
"""FFBC8 weatherstation receive GPS data."""
import logging

from flask import request
from flask_restx import Resource
import requests
from api.restx import API

import settings
NS = API.namespace(
    'GPS',
    description='receive GPS data'
)


@NS.route('/')
class GPS(Resource):
    """Receive GPS data API Class."""

    logger = None

    # pylint: disable=keyword-arg-before-vararg
    def __init__(self, api=None, *args, **kwargs):
        Resource.__init__(self, api, kwargs)
        self.logger = logging.getLogger(__name__)

    def _send_influx(self, data):