Пример #1
0
    def __init__(self,
                 url: Union[AnyHttpUrl, str] = None,
                 *,
                 session: requests.Session = None,
                 fiware_header: Union[Dict, FiwareHeader] = None,
                 **kwargs):

        self.logger = logging.getLogger(name=f"{self.__class__.__module__}."
                                        f"{self.__class__.__name__}")
        self.logger.addHandler(logging.NullHandler())
        self.logger.debug("Creating %s", self.__class__.__name__)

        if url:
            self.logger.debug("Checking url style...")
            self.base_url = validate_http_url(url)

        if session:
            self.session = session
            self._external_session = True
        else:
            self.session = None
            self._headers = {}

        if not fiware_header:
            self.fiware_headers = FiwareHeader()
        else:
            self.fiware_headers = fiware_header

        self.headers.update(kwargs.pop('headers', {}))
        self.kwargs: Dict = kwargs
Пример #2
0
    def setUp(self) -> None:
        """
        Setup test data
        Returns:
            None
        """
        self.fiware_header = FiwareHeader(
            service=settings.FIWARE_SERVICE,
            service_path=settings.FIWARE_SERVICEPATH)
        self.ql_client = QuantumLeapClient(url=settings.QL_URL,
                                           fiware_header=self.fiware_header)

        self.cb_client = ContextBrokerClient(url=settings.CB_URL,
                                             fiware_header=self.fiware_header)
Пример #3
0
 def setUp(self) -> None:
     self.fiware_header = FiwareHeader(
         service=settings.FIWARE_SERVICE,
         service_path=settings.FIWARE_SERVICEPATH)
     clear_all(fiware_header=self.fiware_header,
               cb_url=settings.CB_URL,
               iota_url=settings.IOTA_JSON_URL)
     self.service_group1 = ServiceGroup(entity_type='Thing',
                                        resource='/iot/json',
                                        apikey=str(uuid4()))
     self.service_group2 = ServiceGroup(entity_type='OtherThing',
                                        resource='/iot/json',
                                        apikey=str(uuid4()))
     self.device = {
         "device_id": "test_device",
         "service": self.fiware_header.service,
         "service_path": self.fiware_header.service_path,
         "entity_name": "test_entity",
         "entity_type": "test_entity_type",
         "timezone": 'Europe/Berlin',
         "timestamp": None,
         "apikey": "1234",
         "endpoint": None,
         "transport": 'HTTP',
         "expressionLanguage": None
     }
     self.client = IoTAClient(
         url=settings.IOTA_JSON_URL,
         fiware_header=self.fiware_header)
Пример #4
0
 def test_fiware_header(self):
     """
     Test for fiware header
     """
     header = FiwareHeader.parse_obj(self.fiware_header)
     self.assertEqual(header.dict(by_alias=True), self.fiware_header)
     self.assertEqual(header.json(by_alias=True),
                      json.dumps(self.fiware_header))
     self.assertRaises(ValidationError,
                       FiwareHeader,
                       service='jkgsadh ',
                       service_path='/testing')
     self.assertRaises(ValidationError,
                       FiwareHeader,
                       service='%',
                       service_path='/testing')
     self.assertRaises(ValidationError,
                       FiwareHeader,
                       service='filip',
                       service_path='testing/')
     self.assertRaises(ValidationError,
                       FiwareHeader,
                       service='filip',
                       service_path='/$testing')
     self.assertRaises(ValidationError,
                       FiwareHeader,
                       service='filip',
                       service_path='/testing ')
     self.assertRaises(ValidationError,
                       FiwareHeader,
                       service='filip',
                       service_path='#')
     headers = FiwareHeader.parse_obj(self.fiware_header)
     with ContextBrokerClient(url=settings.CB_URL,
                              fiware_header=headers) as client:
         entity = ContextEntity(id='myId', type='MyType')
         for path in self.service_paths:
             client.fiware_service_path = path
             client.post_entity(entity=entity)
             client.get_entity(entity_id=entity.id)
         client.fiware_service_path = '/#'
         self.assertGreaterEqual(len(client.get_entity_list()),
                                 len(self.service_paths))
         for path in self.service_paths:
             client.fiware_service_path = path
             client.delete_entity(entity_id=entity.id,
                                  entity_type=entity.type)
Пример #5
0
    def __init__(self):
        """Initialization"""
        # # use envirnment variables
        # os.environ["CONFIG_FILE"] = "False"
        # define parameters
        self.params = {}
        self.params['controller_name'] = os.getenv("CONTROLLER_NAME", 'PID_1')
        self.params['type'] = "PID_Controller"
        self.params['setpoint'] = float(os.getenv("SETPOINT", '293.15'))
        # reverse mode can be activated by passing negative tunings to controller
        self.params['Kp'] = float(os.getenv("KP", '1.0'))
        self.params['Ki'] = float(os.getenv("KI", '0'))
        self.params['Kd'] = float(os.getenv("KD", '0'))
        self.params['lim_low'] = float(os.getenv("LIM_LOW", '0'))
        self.params['lim_upper'] = float(os.getenv("LIM_UPPER", '100'))
        self.params['pause_time'] = float(os.getenv("PAUSE_TIME", 0.2))
        self.params['sensor_entity_name'] = os.getenv("SENSOR_ENTITY_NAME", '')
        self.params['sensor_type'] = os.getenv("SENSOR_TYPE", None)
        self.params['sensor_attr'] = os.getenv("SENSOR_ATTR", '')
        self.params['actuator_entity_name'] = os.getenv(
            "ACTUATOR_ENTITY_NAME", '')
        self.params['actuator_type'] = os.getenv("ACTUATOR_TYPE", '')
        self.params['actuator_command'] = os.getenv("ACTUATOR_COMMAND", '')
        self.params['actuator_command_value'] = self.params[
            'actuator_command'] + '_info'
        self.params['service'] = os.getenv("FIWARE_SERVICE", '')
        self.params['service_path'] = os.getenv("FIWARE_SERVICE_PATH", '')
        self.params['cb_url'] = os.getenv("CB_URL", "http://localhost:1026")

        # settings for security mode
        self.security_mode = os.getenv("SECURITY_MODE",
                                       'False').lower() in ('true', '1', 'yes')
        self.params['token'] = (None, None)
        # Get token from keycloak in security mode
        if self.security_mode:
            self.kp = KeycloakPython()
            self.params['token'] = self.kp.get_access_token()

        # Create simple pid instance
        self.pid = PID(self.params['Kp'],
                       self.params['Ki'],
                       self.params['Kd'],
                       setpoint=self.params['setpoint'],
                       output_limits=(self.params['lim_low'],
                                      self.params['lim_upper']))

        # Additional parameters
        self.auto_mode = True
        self.u = None  # control variable u
        self.y_act = self.params[
            'setpoint']  # set the initial measurement to set point

        # Create the fiware header
        fiware_header = FiwareHeader(service=self.params['service'],
                                     service_path=self.params['service_path'])

        # Create orion context broker client
        self.ORION_CB = ContextBrokerClient(url=self.params['cb_url'],
                                            fiware_header=fiware_header)
Пример #6
0
    def setUp(self) -> None:
        """
        Setup test data
        Returns:
            None
        """
        self.fiware_header = FiwareHeader(
            service=settings.FIWARE_SERVICE,
            service_path=settings.FIWARE_SERVICEPATH)
        clear_all(fiware_header=self.fiware_header,
                  cb_url=settings.CB_URL,
                  iota_url=settings.IOTA_JSON_URL)
        self.resources = {
            "entities_url": "/v2/entities",
            "types_url": "/v2/types",
            "subscriptions_url": "/v2/subscriptions",
            "registrations_url": "/v2/registrations"
        }
        self.attr = {'temperature': {'value': 20.0,
                                     'type': 'Number'}}
        self.entity = ContextEntity(id='MyId', type='MyType', **self.attr)


        self.client = ContextBrokerClient(
            url=settings.CB_URL,
            fiware_header=self.fiware_header)
        self.subscription = Subscription.parse_obj({
            "description": "One subscription to rule them all",
            "subject": {
                "entities": [
                    {
                        "idPattern": ".*",
                        "type": "Room"
                    }
                ],
                "condition": {
                    "attrs": [
                        "temperature"
                    ],
                    "expression": {
                        "q": "temperature>40"
                    }
                }
            },
            "notification": {
                "http": {
                    "url": "http://localhost:1234"
                },
                "attrs": [
                    "temperature",
                    "humidity"
                ]
            },
            "expires": datetime.now(),
            "throttling": 0
        })
Пример #7
0
    def tearDown(self) -> None:
        # Cleanup test server
        with ContextBrokerClient(url=settings.CB_URL) as client:
            client.fiware_service = settings.FIWARE_SERVICE

            for path in self.service_paths:
                header = FiwareHeader(service=settings.FIWARE_SERVICE,
                                      service_path=path)
                clear_all(fiware_header=header, cb_url=settings.CB_URL)
            client.close()
Пример #8
0
    def test_subscription_models(self) -> None:
        """
        Test subscription models
        Returns:
            None
        """
        sub_dict = {
            "description": "One subscription to rule them all",
            "subject": {
                "entities": [
                    {
                        "idPattern": ".*",
                        "type": "Room"
                    }
                ],
                "condition": {
                    "attrs": [
                        "temperature"
                    ],
                    "expression": {
                        "q": "temperature>40"
                    }
                }
            },
            "notification": {
                "http": {
                    "url": "http://localhost:1234"
                },
                "attrs": [
                    "temperature",
                    "humidity"
                ]
            },
            "expires": "2030-04-05T14:00:00Z",
            "throttling": 5
        }

        sub = Subscription.parse_obj(sub_dict)
        fiware_header = FiwareHeader(service=settings.FIWARE_SERVICE,
                                     service_path=settings.FIWARE_SERVICEPATH)
        with ContextBrokerClient(
                url=settings.CB_URL,
                fiware_header=fiware_header) as client:
            sub_id = client.post_subscription(subscription=sub)
            sub_res = client.get_subscription(subscription_id=sub_id)

            def compare_dicts(dict1: dict, dict2: dict):
                for key, value in dict1.items():
                    if isinstance(value, dict):
                        compare_dicts(value, dict2[key])
                    else:
                        self.assertEqual(str(value), str(dict2[key]))

            compare_dicts(sub.dict(exclude={'id'}),
                          sub_res.dict(exclude={'id'}))
Пример #9
0
 def setUp(self) -> None:
     """
     Setup test data
     Returns:
         None
     """
     self.fh = FiwareHeader(service=settings.FIWARE_SERVICE,
                            service_path=settings.FIWARE_SERVICEPATH)
     self.create_json_file()
     with open(self.get_json_path()) as f:
         self.config = json.load(f)
Пример #10
0
def create_time_series_data(num_records: int = 50000):
    """
    creates large testing data sets that should remain on the server.
    This is mainly to reduce time for testings
    """
    fiware_header = FiwareHeader(service=settings.FIWARE_SERVICE,
                                 service_path="/static")

    with QuantumLeapClient(url=settings.QL_URL, fiware_header=fiware_header) \
            as client:

        for i in range(num_records):
            notification_message = Message(data=create_entities(),
                                           subscriptionId="test")
            client.post_notification(notification_message)
Пример #11
0
    def fiware_headers(self, headers: Union[Dict, FiwareHeader]) -> None:
        """
        Sets new fiware header

        Args:
            headers (Dict, FiwareHeader): New headers either as FiwareHeader
                object or as dict.

        Example:
            {fiware-service: "MyService",
             fiware-servicepath: "/MyServicePath"}

        Returns:
            None
        """
        if isinstance(headers, FiwareHeader):
            self._fiware_headers = headers
        elif isinstance(headers, dict):
            self._fiware_headers = FiwareHeader.parse_obj(headers)
        elif isinstance(headers, str):
            self._fiware_headers = FiwareHeader.parse_raw(headers)
        else:
            raise TypeError(f'Invalid headers! {type(headers)}')
        self.headers.update(self.fiware_headers.dict(by_alias=True))
Пример #12
0
    def generate_mutltitenancy_setup(cls, values):
        """
        Tests if the fields for multi tenancy in fiware are consistent.
        If CI_JOB_ID is present it will always overwrite the service path.
        Args:
            values: class variables

        Returns:

        """
        if values.get('CI_JOB_ID', None):
            values['FIWARE_SERVICEPATH'] = f"/{values['CI_JOB_ID']}"

        FiwareHeader(service=values['FIWARE_SERVICE'],
                     service_path=values['FIWARE_SERVICEPATH'])

        return values
Пример #13
0
    def __init__(self):
        # initialize controller parameters (in dict)
        self.params = self.initialize_params()

        # FIWARE parameters
        self.cb_url = os.getenv("CB_URL", "http://localhost:1026")
        self.entity_id = None  # will be read on the web GUI
        self.entity_type = "PID_Controller"
        self.service = os.getenv("FIWARE_SERVICE", '')
        self.service_path = os.getenv("FIWARE_SERVICE_PATH", '')

        # Create the fiware header
        fiware_header = FiwareHeader(service=self.service,
                                     service_path=self.service_path)

        # Create orion context broker client
        self.ORION_CB = ContextBrokerClient(url=self.cb_url,
                                            fiware_header=fiware_header)

        # initial pid controller list
        self.controller_list = []
        try:
            self.refresh_list()
        except:
            pass

        # initialize gui window
        sg.theme("DarkBlue")
        pid_id_bar = [[
            sg.Text("Controller ID", size=(10, 1)),
            sg.Combo(self.controller_list, key="controller_list"),
            sg.Button("Refresh")
        ]]
        param_bars = [[
            sg.Text(param.capitalize(), size=(10, 1)),
            sg.InputText(self.params[param], key=param)
        ] for param in self.params.keys()]
        io_bars = [[sg.Button("Send"), sg.Button("Read")]]
        layout = pid_id_bar + param_bars + io_bars
        self.window = sg.Window("PID controller",
                                layout,
                                web_port=80,
                                web_start_browser=True)
Пример #14
0
 def setUp(self) -> None:
     """
     Setup test data
     Returns:
         None
     """
     self.fiware_header = FiwareHeader(
         service=settings.FIWARE_SERVICE,
         service_path=settings.FIWARE_SERVICEPATH)
     self.http_url = "https://test.de:80"
     self.mqtt_url = "mqtt://test.de:1883"
     self.mqtt_topic = '/filip/testing'
     self.notification = {
         "http":
         {
             "url": "http://localhost:1234"
         },
         "attrs": [
             "temperature",
             "humidity"
         ]
     }
Пример #15
0
service = 'filip'
# FIWARE-Servicepath
service_path = '/example'

if __name__ == '__main__':

    # # 1 FiwareHeader
    #
    # First a create a fiware header that you want to work with
    # For more details on the headers check the official documentation:
    # https://fiware-orion.readthedocs.io/en/master/user/multitenancy/index.html
    #
    # In short a fiware header specifies a location in Fiware where the
    # created entities will be saved and requests are executed.
    # It can be thought of as a separated subdirectory where you work in.
    fiware_header = FiwareHeader(service='filip', service_path='/example')

    # # 2 Client modes
    # You can run the clients in different modes:
    #
    # ## 2.1 Run it as pure python object.
    #
    # This will open and close a connection each time you use a function.
    cb_client = ContextBrokerClient(url="http://134.130.166.184:1026",
                                    fiware_header=fiware_header)
    print(f"OCB Version: {cb_client.get_version()}")

    # ## 2.2 Run the client via the python's context protocol.
    #
    # This will initialize requests.session that the client will reuse for
    # each function.
Пример #16
0
    def test_strings_in_models(self) -> None:
        """
        Tests for each not fixed key, and for each value the reaction if
        a ' or " is added to the string

        Either it is allowed, than the posting of an entity with the
        key/string succeeds
        Or it is forbidden than the Model needs to throw an error
        """

        entity_dict = {
            "id": 'MyId',
            "type": 'MyType',
            'at1': {
                'value': "20.0",
                'type': 'Text'
            },
            'at2': {
                'value': {
                    'field_value': "20.0"
                },
                'type': 'StructuredValue',
                'metadata': {
                    'name': 'test-name',
                    'type': 'StructuredValue',
                    'value': {
                        'field_value': "20.0"
                    },
                }
            }
        }

        def field_value_tests(dictionary: dict,
                              keychain: List[str],
                              test_keys: bool = False):
            """Recursively test the keys, values of a dictionary that will be
            transformed into an entity.

            Args:
                dictionary: Entity in dictionary form
                keychain: List of keys from the top level of the dict to the
                        currently analysed level
                test_keys: True if also the modification of the keys should
                        be checked

            """
            for field, value in dictionary.items():
                if isinstance(value, dict):
                    # If still a dict than continue recursively
                    keychain_ = copy.copy(keychain)
                    keychain_.append(field)

                    field_value_tests(value, keychain_, field == "value")
                else:
                    # we have a key value pair both strings
                    for test_char, needs_to_succeed in [("'", False),
                                                        ('"', False),
                                                        ("", True)]:
                        # Append ', " or nothing. The last is not allowed to
                        # fail

                        def test(dictionary: Dict):
                            # either the assignment throws an error or
                            # the entity can get posted and gets found

                            assignment_error = False
                            try:
                                entity = ContextEntity(**dictionary)
                            except:
                                assignment_error = True
                                self.assertFalse(needs_to_succeed)

                            if not assignment_error:
                                client.post_entity(entity=entity)
                                # if post successful get will not throw an
                                # error
                                client.get_entity(entity_id=entity.id,
                                                  entity_type=entity.type)
                                client.delete_entity(entity_id=entity.id,
                                                     entity_type=entity.type)

                        # work on a copy
                        new_dict = copy.deepcopy(entity_dict)

                        # find the current key pair in the dict
                        dict_field = new_dict
                        for key in keychain:
                            dict_field = dict_field[key]

                        # apply the modification and test
                        value_ = dict_field[field]
                        dict_field[field] = f'{value}{test_char}'
                        test(new_dict)

                        # if keys should be tested, apply the modification to
                        # key and test
                        if test_keys:
                            del dict_field[field]
                            dict_field[f'{field}{test_char}'] = value_
                            test(new_dict)

        header = FiwareHeader.parse_obj(self.fiware_header)
        with ContextBrokerClient(url=settings.CB_URL,
                                 fiware_header=header) as client:

            field_value_tests(entity_dict, [])
Пример #17
0
"""
To run this example you need a working Fiware v2 setup with a context-broker 
and an iota-broker. You can here set the addresses:
"""
cb_url = "http://localhost:1026"
iota_url = "http://localhost:4041"

if __name__ == '__main__':

    # # 0 Clean up Fiware state:
    #
    # For this example to work the fiware state needs to be clean:
    from filip.models.base import FiwareHeader
    from filip.utils.cleanup import clear_all

    fiware_header = FiwareHeader(service="example", service_path="/")
    clear_all(fiware_header=fiware_header, cb_url=cb_url, iota_url=iota_url)

    # # 1 Import Models
    #
    # First we need to import the models that we have created in the
    # "semantics_vocabulary_example" and exported into the file "models.py".
    # Each vocabulary class was converted to a python class and can now be
    # instantiated.
    # Additionally the class semantic_manager is created and will be used to
    # manage the local state as well as save it.
    # It is important that we only import one vocabulary model file,
    # if we want to use multiple models, we need to combine them in a
    # vocabulary and export them as one file.

    # We can import the classes selectively or all at once
Пример #18
0
class TestTimeSeries(unittest.TestCase):
    """
    Test class for time series api client
    """
    def setUp(self) -> None:
        """
        Setup test data
        Returns:
            None
        """
        self.fiware_header = FiwareHeader(
            service=settings.FIWARE_SERVICE,
            service_path=settings.FIWARE_SERVICEPATH)
        self.ql_client = QuantumLeapClient(url=settings.QL_URL,
                                           fiware_header=self.fiware_header)

        self.cb_client = ContextBrokerClient(url=settings.CB_URL,
                                             fiware_header=self.fiware_header)

    def test_meta_endpoints(self) -> None:
        """
        Test meta data endpoints
        Returns:
            None
        """
        with QuantumLeapClient(
                url=settings.QL_URL,
                fiware_header=self.fiware_header) \
                as client:
            self.assertIsNotNone(client.get_version())
            self.assertIsNotNone(client.get_health())

    @clean_test(fiware_service=settings.FIWARE_SERVICE,
                fiware_servicepath=settings.FIWARE_SERVICEPATH,
                cb_url=settings.CB_URL,
                ql_url=settings.QL_URL)
    def test_input_endpoints(self) -> None:
        """
        Test input endpoint
        Returns:
            None
        """
        entities = create_entities()
        for entity in entities:
            self.cb_client.post_entity(entity)

        with QuantumLeapClient(
                url=settings.QL_URL,
                fiware_header=self.fiware_header) \
                as client:
            notification_message = Message(data=entities,
                                           subscriptionId="test")
            client.post_subscription(cb_url=settings.CB_URL,
                                     ql_url=settings.QL_URL,
                                     entity_id=entities[0].id)
            client.post_notification(notification_message)
        time.sleep(1)

    @clean_test(fiware_service=settings.FIWARE_SERVICE,
                fiware_servicepath=settings.FIWARE_SERVICEPATH,
                ql_url=settings.QL_URL)
    def test_entity_context(self) -> None:
        """
        Test entities endpoint
        Returns:
            None
        """
        entities = create_entities()
        with QuantumLeapClient(
                url=settings.QL_URL,
                fiware_header=self.fiware_header) \
                as client:
            notification_message = Message(data=entities,
                                           subscriptionId="test")
            client.post_notification(notification_message)

            time.sleep(1)
            entities = client.get_entities(entity_type=entities[0].type)
            for entity in entities:
                logger.debug(entity.json(indent=2))

    def test_query_endpoints_by_id(self) -> None:
        """
        Test queries with default values

        Returns:
            None
        """
        with QuantumLeapClient(
                url=settings.QL_URL,
                fiware_header=self.fiware_header.copy(
                    update={'service_path': '/static'})) \
                as client:

            entities = create_entities()

            with self.assertRaises(requests.RequestException):
                client.get_entity_by_id(entity_id=entities[0].id,
                                        entity_type='MyType')
            for entity in entities:
                # get by id
                attrs_id = client.get_entity_by_id(entity_id=entity.id,
                                                   aggr_period='minute',
                                                   aggr_method='avg',
                                                   attrs='temperature,co2')
                logger.debug(attrs_id.json(indent=2))
                logger.debug(attrs_id.to_pandas())

                attrs_values_id = client.get_entity_values_by_id(
                    entity_id=entity.id)
                logger.debug(attrs_values_id.to_pandas())
                self.assertEqual(len(attrs_values_id.index), 10000)

                attr_id = client.get_entity_attr_by_id(entity_id=entity.id,
                                                       attr_name="temperature")
                logger.debug(attr_id.to_pandas())
                self.assertEqual(len(attr_id.index), 10000)

                attr_values_id = client.get_entity_attr_values_by_id(
                    entity_id=entity.id, attr_name="temperature")
                logger.debug(attr_values_id.to_pandas())
                self.assertEqual(len(attrs_values_id.index), 10000)

    def test_query_endpoints_by_type(self) -> None:
        """
        Test queries by type with default values

        Returns:
            None
        """
        with QuantumLeapClient(
                url=settings.QL_URL,
                fiware_header=self.fiware_header.copy(
                    update={'service_path': '/static'})) \
                as client:

            entities = create_entities()

            for entity in entities:
                # get by type
                attrs_type = client.get_entity_by_type(entity_type=entity.type)
                for entity_id in attrs_type:
                    logger.debug(entity_id.to_pandas())

                self.assertEqual(
                    sum([len(entity_id.index) for entity_id in attrs_type]),
                    10000)

                attrs_values_type = client.get_entity_values_by_type(
                    entity_type=entity.type, )
                for entity_id in attrs_values_type:
                    logger.debug(entity_id.to_pandas())
                self.assertEqual(
                    sum([
                        len(entity_id.index) for entity_id in attrs_values_type
                    ]), 10000)

                attr_type = client.get_entity_attr_by_type(
                    entity_type=entity.type, attr_name="temperature")
                for entity_id in attr_type:
                    logger.debug(entity_id.to_pandas())
                self.assertEqual(
                    sum([len(entity_id.index) for entity_id in attr_type]),
                    10000)

                attr_values_type = client.get_entity_attr_values_by_type(
                    entity_type=entity.type, attr_name="temperature")
                for entity_id in attr_values_type:
                    logger.debug(entity_id.to_pandas())
                self.assertEqual(
                    sum([
                        len(entity_id.index) for entity_id in attr_values_type
                    ]), 10000)

    def test_test_query_endpoints_with_args(self) -> None:
        """
        Test arguments for queries

        Returns:
            None
        """
        with QuantumLeapClient(
                url=settings.QL_URL,
                fiware_header=self.fiware_header.copy(
                    update={'service_path': '/static'})) \
                as client:

            for entity in create_entities():
                # test limit
                for limit in range(5000, 25000, 5000):
                    records = client.get_entity_by_id(entity_id=entity.id,
                                                      attrs='temperature,co2',
                                                      limit=limit)

                    logger.debug(records.json(indent=2))
                    logger.debug(records.to_pandas())
                    self.assertEqual(len(records.index), limit)

                # test last_n
                for last_n in range(5000, 25000, 5000):
                    limit = 15000
                    last_n_records = client.get_entity_by_id(
                        entity_id=entity.id,
                        attrs='temperature,co2',
                        limit=limit,
                        last_n=last_n)
                    self.assertGreater(last_n_records.index[0],
                                       records.index[0])
                    self.assertEqual(len(last_n_records.index),
                                     min(last_n, limit))

                # test offset
                old_records = None
                for offset in range(5000, 25000, 5000):
                    # with limit
                    records = client.get_entity_by_id(entity_id=entity.id,
                                                      attrs='temperature,co2',
                                                      offset=offset)

                    if old_records:
                        self.assertLess(old_records.index[0], records.index[0])
                    old_records = records

                old_records = None
                for offset in range(5000, 25000, 5000):
                    # test with last_n
                    records = client.get_entity_by_id(entity_id=entity.id,
                                                      attrs='temperature,co2',
                                                      offset=offset,
                                                      last_n=5)
                    if old_records:
                        self.assertGreater(old_records.index[0],
                                           records.index[0])
                    old_records = records

    def tearDown(self) -> None:
        """
        Clean up server
        Returns:
            None
        """
        clear_all(fiware_header=self.fiware_header,
                  cb_url=settings.CB_URL,
                  ql_url=settings.QL_URL)

        self.ql_client.close()
        self.cb_client.close()
Пример #19
0
class BaseHttpClient:
    """
    Base client for all derived api-clients.

    Args:
        session: request session object. This is required for reusing
            the same connection
        reuse_session (bool):
        fiware_header: Fiware header object required for multi tenancy
        **kwargs: Optional arguments that ``request`` takes.

    """
    def __init__(self,
                 url: Union[AnyHttpUrl, str] = None,
                 *,
                 session: requests.Session = None,
                 fiware_header: Union[Dict, FiwareHeader] = None,
                 **kwargs):

        self.logger = logging.getLogger(name=f"{self.__class__.__module__}."
                                        f"{self.__class__.__name__}")
        self.logger.addHandler(logging.NullHandler())
        self.logger.debug("Creating %s", self.__class__.__name__)

        if url:
            self.logger.debug("Checking url style...")
            self.base_url = validate_http_url(url)

        if session:
            self.session = session
            self._external_session = True
        else:
            self.session = None
            self._headers = {}

        if not fiware_header:
            self.fiware_headers = FiwareHeader()
        else:
            self.fiware_headers = fiware_header

        self.headers.update(kwargs.pop('headers', {}))
        self.kwargs: Dict = kwargs

    # Context Manager Protocol
    def __enter__(self):
        if not self.session:
            self.session = requests.Session()
            self.headers.update(self.fiware_headers.dict(by_alias=True))
            self._external_session = False
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    @property
    def fiware_headers(self) -> FiwareHeader:
        """
        Get fiware header

        Returns:
            FiwareHeader
        """
        return self._fiware_headers

    @fiware_headers.setter
    def fiware_headers(self, headers: Union[Dict, FiwareHeader]) -> None:
        """
        Sets new fiware header

        Args:
            headers (Dict, FiwareHeader): New headers either as FiwareHeader
                object or as dict.

        Example:
            {fiware-service: "MyService",
             fiware-servicepath: "/MyServicePath"}

        Returns:
            None
        """
        if isinstance(headers, FiwareHeader):
            self._fiware_headers = headers
        elif isinstance(headers, dict):
            self._fiware_headers = FiwareHeader.parse_obj(headers)
        elif isinstance(headers, str):
            self._fiware_headers = FiwareHeader.parse_raw(headers)
        else:
            raise TypeError(f'Invalid headers! {type(headers)}')
        self.headers.update(self.fiware_headers.dict(by_alias=True))

    @property
    def fiware_service(self) -> str:
        """
        Get current fiware service
        Returns:
            str
        """
        return self.fiware_headers.service

    @fiware_service.setter
    def fiware_service(self, service: str) -> None:
        """
        Set new fiware service
        Args:
            service:

        Returns:
            None
        """
        self._fiware_headers.service = service
        self.headers.update(self.fiware_headers.dict(by_alias=True))

    @property
    def fiware_service_path(self) -> str:
        """
        Get current fiware service path
        Returns:
            str
        """
        return self.fiware_headers.service_path

    @fiware_service_path.setter
    def fiware_service_path(self, service_path: str) -> None:
        """
        Set new fiware service path
        Args:
            service_path (str): New fiware service path. Must start with '/'

        Returns:
            None
        """
        self._fiware_headers.service_path = service_path
        self.headers.update(self.fiware_headers.dict(by_alias=True))

    @property
    def headers(self):
        """
        Return current session headers
        Returns:
            dict with headers
        """
        if self.session:
            return self.session.headers
        return self._headers

    # modification to requests api
    def get(self,
            url: str,
            params: Union[Dict, List[Tuple], ByteString] = None,
            **kwargs) -> requests.Response:
        """
        Sends a GET request either using the provided session or the single
        session.

        Args:
            url (str): URL for the new :class:`Request` object.
            params (optional): (optional) Dictionary, list of tuples or bytes
                to send in the query string for the :class:`Request`.
            **kwargs: Optional arguments that ``request`` takes.

        Returns:
            requests.Response
        """

        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.get(url=url, params=params, **kwargs)
        return requests.get(url=url, params=params, **kwargs)

    def options(self, url: str, **kwargs) -> requests.Response:
        """
        Sends an OPTIONS request either using the provided session or the
        single session.

        Args:
            url (str):
            **kwargs: Optional arguments that ``request`` takes.

        Returns:
            requests.Response
        """
        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.options(url=url, **kwargs)
        return requests.options(url=url, **kwargs)

    def head(self,
             url: str,
             params: Union[Dict, List[Tuple], ByteString] = None,
             **kwargs) -> requests.Response:
        """
        Sends a HEAD request either using the provided session or the
        single session.

        Args:
            url (str): URL for the new :class:`Request` object.
            params (optional): Dictionary, list of tuples or bytes
                to send in the query string for the :class:`Request`.
            **kwargs: Optional arguments that ``request`` takes.

        Returns:
            requests.Response
        """
        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.head(url=url, params=params, **kwargs)
        return requests.head(url=url, params=params, **kwargs)

    def post(self,
             url: str,
             data: Union[Dict, ByteString, List[Tuple], IO, str] = None,
             json: Dict = None,
             **kwargs) -> requests.Response:
        """
        Sends a POST request either using the provided session or the
        single session.

        Args:
            url: URL for the new :class:`Request` object.
            data: Dictionary, list of tuples, bytes, or file-like object to
                send in the body of the :class:`Request`.
            json: A JSON serializable Python object to send in the
                body of the :class:`Request`.
            **kwargs: Optional arguments that ``request`` takes.

        Returns:

        """
        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.post(url=url, data=data, json=json, **kwargs)
        return requests.post(url=url, data=data, json=json, **kwargs)

    def put(self,
            url: str,
            data: Union[Dict, ByteString, List[Tuple], IO, str] = None,
            json: Dict = None,
            **kwargs) -> requests.Response:
        """
        Sends a PUT request either using the provided session or the
        single session.

        Args:
            url: URL for the new :class:`Request` object.
            data (Union[Dict, ByteString, List[Tuple], IO]):
                Dictionary, list of tuples, bytes, or file-like
                object to send in the body of the :class:`Request`.
            json (Dict): A JSON serializable Python object to send in the
                body of the :class:`Request`..
            **kwargs: Optional arguments that ``request`` takes.

        Returns:
            request.Response
        """
        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.put(url=url, data=data, json=json, **kwargs)
        return requests.put(url=url, data=data, json=json, **kwargs)

    def patch(self,
              url: str,
              data: Union[Dict, ByteString, List[Tuple], IO, str] = None,
              json: Dict = None,
              **kwargs) -> requests.Response:
        """
        Sends a PATCH request either using the provided session or the
        single session.

        Args:
            url: URL for the new :class:`Request` object.
            data (Union[Dict, ByteString, List[Tuple], IO]):
                Dictionary, list of tuples, bytes, or file-like
                object to send in the body of the :class:`Request`.
            json (Dict): A JSON serializable Python object to send in the
                body of the :class:`Request`..
            **kwargs: Optional arguments that ``request`` takes.

        Returns:
            request.Response
        """
        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.patch(url=url, data=data, json=json, **kwargs)
        return requests.patch(url=url, data=data, json=json, **kwargs)

    def delete(self, url: str, **kwargs) -> requests.Response:
        """
        Sends a DELETE request either using the provided session or the
        single session.

        Args:
            url (str): URL for the new :class:`Request` object.
            **kwargs: Optional arguments that ``request`` takes.

        Returns:
            request.Response
        """
        kwargs.update(
            {k: v
             for k, v in self.kwargs.items() if k not in kwargs.keys()})

        if self.session:
            return self.session.delete(url=url, **kwargs)
        return requests.delete(url=url, **kwargs)

    def log_error(self,
                  err: requests.RequestException,
                  msg: str = None) -> None:
        """
        Outputs the error messages from the client request function. If
        additional information is available in the server response this will
        be forwarded to the logging output.

        Note:
            The user is responsible to setup the logging system

        Args:
            err: Request Error
            msg: error message from calling function

        Returns:
            None
        """
        if err.response is not None:
            if err.response.text and msg:
                self.logger.error("%s \n Reason: %s", msg, err.response.text)
            elif err.response.text and not msg:
                self.logger.error("%s", err.response.text)
        elif not err.response and msg:
            self.logger.error("%s \n Reason: %s", msg, err)
        else:
            self.logger.error(err)

    def close(self) -> None:
        """
        Close http session
        Returns:
            None
        """
        if self.session and not self._external_session:
            self.session.close()
Пример #20
0
def simulation(
    TEMPERATURE_MAX=10,  # maximal ambient temperature
    TEMPERATURE_MIN=-5,  # minimal ambient temperature
    TEMPERATURE_ZONE_START=10,  # start value of the zone temperature
    T_SIM_START=0,  # simulation start time in seconds
    T_SIM_END=24 * 60 * 60,  # simulation end time in seconds
    COM_STEP=60 * 15,  # 1 min communication step in seconds
    SLEEP_TIME=0.2  # sleep time between every simulation step
):
    # create a fiware header object
    fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH)

    # instantiate simulation model
    sim_model = SimulationModel(t_start=T_SIM_START,
                                t_end=T_SIM_END,
                                temp_max=TEMPERATURE_MAX,
                                temp_min=TEMPERATURE_MIN,
                                temp_start=TEMPERATURE_ZONE_START)

    # Create clients and restore devices and groups from files
    groups = parse_file_as(List[ServiceGroup], READ_GROUPS_FILEPATH)
    devices = parse_file_as(List[Device], READ_DEVICES_FILEPATH)
    cbc = ContextBrokerClient(url=CB_URL, fiware_header=fiware_header)
    iotac = IoTAClient(url=IOTA_URL, fiware_header=fiware_header)
    iotac.post_groups(service_groups=groups, update=True)
    iotac.post_devices(devices=devices, update=True)

    # Get the device configurations from the server
    weather_station = iotac.get_device(device_id="device:001")
    zone_temperature_sensor = iotac.get_device(device_id="device:002")
    heater = iotac.get_device(device_id="device:003")

    # Get the service group configurations from the server
    group = iotac.get_group(resource="/iot/json", apikey=APIKEY)

    #  Create a http subscriptions that get triggered by updates of your
    #  device attributes and send data to Quantum Leap.
    qlc = QuantumLeapClient(url=QL_URL, fiware_header=fiware_header)

    qlc.post_subscription(entity_id=weather_station.entity_name,
                          entity_type=weather_station.entity_type,
                          cb_url="http://orion:1026",
                          ql_url="http://quantumleap:8668",
                          throttling=0)

    qlc.post_subscription(entity_id=zone_temperature_sensor.entity_name,
                          entity_type=zone_temperature_sensor.entity_type,
                          cb_url="http://orion:1026",
                          ql_url="http://quantumleap:8668",
                          throttling=0)

    qlc.post_subscription(entity_id=heater.entity_name,
                          entity_type=heater.entity_type,
                          cb_url="http://orion:1026",
                          ql_url="http://quantumleap:8668",
                          throttling=0)

    # create a MQTTv5 client with paho-mqtt and the known groups and devices.
    mqttc = IoTAMQTTClient(
        protocol=mqtt.MQTTv5,
        devices=[weather_station, zone_temperature_sensor, heater],
        service_groups=[group])
    # set user data if required
    mqttc.username_pw_set(username=MQTT_USER, password=MQTT_PW)

    #  Implement a callback function that gets triggered when the
    #  command is sent to the device. The incoming command should update the
    #  heater power of the simulation model
    def on_command(client, obj, msg):
        """
        Callback for incoming commands
        """
        # Decode the message payload using the libraries builtin encoders
        apikey, device_id, payload = \
            client.get_encoder(PayloadProtocol.IOTA_JSON).decode_message(
                msg=msg)
        # Update the heating power of the simulation model
        sim_model.heater_power = payload["heater_power"]

        # Acknowledge the command.
        client.publish(device_id=device_id,
                       command_name=next(iter(payload)),
                       payload=payload)

    # Add the command callback to your MQTTClient. This will get
    #  triggered for the specified device_id
    mqttc.add_command_callback(device_id=heater.device_id, callback=on_command)

    # connect to the mqtt broker and subscribe to your topic
    mqtt_url = urlparse(MQTT_BROKER_URL_EXPOSED)
    mqttc.connect(host=mqtt_url.hostname,
                  port=mqtt_url.port,
                  keepalive=60,
                  bind_address="",
                  bind_port=0,
                  clean_start=mqtt.MQTT_CLEAN_START_FIRST_ONLY,
                  properties=None)
    # subscribe to all incoming command topics for the registered devices
    mqttc.subscribe()

    # create a non-blocking thread for mqtt communication
    mqttc.loop_start()

    # define lists to store historical data
    history_weather_station = []
    history_zone_temperature_sensor = []
    history_heater_power = []

    # simulation without heater
    # Create a loop that publishes regularly a message to the broker
    #  that holds the simulation time "simtime" and the corresponding
    #  temperature "temperature" the loop should. You may use the `object_id`
    #  or the attribute name as key in your payload.
    print("Simulation starts")
    for t_sim in range(sim_model.t_start, sim_model.t_end + int(COM_STEP),
                       int(COM_STEP)):
        # publish the simulated ambient temperature
        mqttc.publish(device_id=weather_station.device_id,
                      payload={
                          "temperature": sim_model.t_amb,
                          "simtime": sim_model.t_sim
                      })

        # publish the simulated zone temperature
        mqttc.publish(device_id=zone_temperature_sensor.device_id,
                      payload={
                          "temperature": sim_model.t_zone,
                          "simtime": sim_model.t_sim
                      })

        # publish the 'simtime' for the heater device
        mqttc.publish(device_id=heater.device_id,
                      payload={"simtime": sim_model.t_sim})

        # simulation step for next loop
        sim_model.do_step(int(t_sim + COM_STEP))
        # wait for one second before publishing the next values
        time.sleep(SLEEP_TIME)

        # Get corresponding entities and write values to history
        weather_station_entity = cbc.get_entity(
            entity_id=weather_station.entity_name,
            entity_type=weather_station.entity_type)
        # append the data to the local history
        history_weather_station.append({
            "simtime":
            weather_station_entity.simtime.value,
            "temperature":
            weather_station_entity.temperature.value
        })

        # Get ZoneTemperatureSensor and write values to history
        zone_temperature_sensor_entity = cbc.get_entity(
            entity_id=zone_temperature_sensor.entity_name,
            entity_type=zone_temperature_sensor.entity_type)
        history_zone_temperature_sensor.append({
            "simtime":
            zone_temperature_sensor_entity.simtime.value,
            "temperature":
            zone_temperature_sensor_entity.temperature.value
        })

        # Get ZoneTemperatureSensor and write values to history
        heater_entity = cbc.get_entity(entity_id=heater.entity_name,
                                       entity_type=heater.entity_type)
        history_heater_power.append({
            "simtime": heater_entity.simtime.value,
            "heater_power": sim_model.heater_power
        })

    # close the mqtt listening thread
    mqttc.loop_stop()
    # disconnect the mqtt device
    mqttc.disconnect()

    clear_iot_agent(url=IOTA_URL, fiware_header=fiware_header)
    clear_context_broker(url=CB_URL, fiware_header=fiware_header)

    return history_weather_station, history_zone_temperature_sensor, history_heater_power
Пример #21
0
# FIWARE-Service
SERVICE = 'filip'
# FIWARE-Servicepath
SERVICE_PATH = '/example'

# Setting up logging
logging.basicConfig(level='INFO',
                    format='%(asctime)s %(name)s %(levelname)s: %(message)s')
logger = logging.getLogger(__name__)

if __name__ == "__main__":
    # # 1 Setup IoTAClient
    #
    # First a client is initialised that provides as access to our
    # Fiware-server space. For more details on this step see e01_http_clients.py
    fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH)
    iota_client = IoTAClient(url=IOTA_URL, fiware_header=fiware_header)

    print("IoTA " + json.dumps(iota_client.get_version(), indent=2) +
          " at url " + iota_client.base_url)

    # # 2 Device Model
    #
    # ## 2.1 Create a device
    #
    # A device can be created in two ways
    # For all information about the needed device attributes, please
    # reference the DeviceModel directly.
    #
    # When a device is posted to Fiware, Fiware will automatically create a
    # ContextEntity that symbolises the current device state. Through the
                    }
                ],
                "attrs": ["temperature", "windspeed"]
            },
            "provider": provider.dict()
        })
    print("+"*80)
    print("Registration that makes the first building a context "
          "provider for the second building")
    print("+"*80)
    print(registration.json(indent=2))


    # # 3 Post created objects to Fiware
    #
    fiware_header = FiwareHeader(service=SERVICE,
                                 service_path=SERVICE_PATH)
    print(fiware_header.json(by_alias=True, indent=2))
    client = ContextBrokerClient(url=CB_URL,
                                 fiware_header=fiware_header)
    client.post_entity(entity=weather_station)
    client.post_entity(entity=building_1)
    registration_id = client.post_registration(registration=registration)
    print(registration_id)


    # # 4 Read in objects from Fiware
    #
    registration = client.get_registration(registration_id=registration_id)
    print(registration.json(indent=2))

    weather_station = client.get_entity(entity_id=weather_station.id,