Git Product home page Git Product logo

filip's People

Contributors

alexanderaku avatar djs0109 avatar felixstege avatar fwuellhorst avatar iripiri avatar maghnie avatar malte96 avatar mwr-ebc avatar rcx112 avatar redingjeff avatar richardmarston avatar sairabano-de avatar sbanoeon avatar sblechmann avatar sebastianborges avatar stv0g avatar stwiemann avatar systemspurge avatar tstorek avatar tzuchen-liu avatar walthertrgovac avatar windrad6 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

filip's Issues

remove unnecessary submodules

currently the repo contains the specifications as submodules. However, this is not necessary and only makes the repo unnessary large.

Test clean up, uses wrong method to clean entities

Describe the bug
Certain tests leave artifacts in the Fiware contextbroker after their clean up.
The clean uses the .update(action_type="delete") function which only deletes the attributes of the entity if it has some, leaving an entity entry with id an type in the broker.

Solution
Replace in clean up function:
client.update(entities=entities, action_type='delete')
with
for entity in entities: client.delete_entity(entity_id=entity.id, entity_type=entity.type)

Cleanup

Removing the author and creation date from the module docstrings.
Also deleted files that are no longer needed.

Add MQTT notifications to CB_client

Is your feature request related to a problem? Please describe.
With the new version of the Orion Context Broker notifications via MQTT are supported.
https://fiware-orion.readthedocs.io/en/3.2.0/user/mqtt_notifications/index.html

Describe the solution you'd like
We want to add this functionality in our notifications models.
Furthermore, we need to introduce the deprecated query parameter for skipping the initial notification for backward compatibility. If set the the client will check the version of the context broker first and then return a warning to the user.

Describe alternatives you've considered
None

ContextEntity: Get Commands

Extend the ContextEntity model with methods to easily access the existing commands and their additional information (status, info)

Requests-Bugfixes

The method post_request does not work, as the http field needs to be in json form:

Current body:
{"provider": {"http": "http://localhost:1234"}, "dataProvided": ...}

Required body:
{"provider": {"http": {"url": "http://localhost:1234" }, ...}

Further this issue will test if existing registrations are correctly removed (or edited) if the corresponding entity is deleted

make loading units a function

Currently, units are automatically loaded on import.
This needs to change in order to make FiLiP PyPy ready.
Erase old code fragments.

better cleanup

Is your feature request related to a problem? Please describe.
Currently, the clean up fuction do not check weather the data is realy deleted. Hence, this should be checked instead of a time.sleep()

Describe the solution you'd like
Substitute time.sleep() with get_requests on list level.

Describe alternatives you've considered
None

Broken test for time series

Describe the bug
The tests for time series leave old subscriptions in orion.
Running multiple test over time will let them pile up.

To Reproduce
Steps to reproduce the behavior:

  1. Run tests for time series several times
  2. check for subscriptions in the context broker

Expected behavior
Subscriptions should be deleted after testing

Solutions
Use teardown at the end of the test case this will delete old subscriptions even if the test fails

adding mqtt client

we like to add an mqtt client that can be directly used with the iotagent-ul or iotagent-json.
The client will be placed in the clients.mqtt

Here is the orginal discussion on the module:

https://git.rwth-aachen.de/EBC/EBC_all/fiware/filip/-/issues/45

The client should especially simplify the topic subscription patterns for the mqtt interface.
This is not trivial in FIWARE:

https://github.com/telefonicaid/iotagent-node-lib/blob/master/doc/api.md#relationship-between-service-groups-and-devices

And also part of current discussions:

https://github.com/telefonicaid/iotagent-json/issues/585

hints for unit validation

Currently, unit validation is very strict. Therefore, we want to add hints to the user in order to find the right unit.

  • write a try and except block that catches the key error from the unit-tables
  • use fuzzywuzzy to generate and provide appropriate error message and hints

Patch_entity and Patch_device.

Sibling methods to post_entity and post_device.

These methods shall allow the user to readout an entity/device from Fiware, edit the object in any way they want and then publish the made changes (while keeping as much of the current Fiware state) to Fiware.

The PATCH Method introduces a simpler and more compressed interface for the user then the currently used UPDATE.
UPDATE has following issues:

  • It does not add new metadata to the fields
  • Does only append fields, does not deleted removed ones
  • The user does need to know if the entity already exists
  • Overwrites current state of fields, even if they were not changed locally in the entity

PATCH allows the user a simpler usage flow.

  1. He downloads a few entities
  2. Deletes/Adds a few fields
  3. Changes values
  4. Creates new entities

With Patch, he can now simply call the patch(entity) method for each entity that he has and does not need to differentiate between cases(new entity, field deleted, ...).

Additionally he can provide the entity_state before his editions to the method to only update the fields that he actively changed, thus he does not override the complete Fiware state of the entity, if there is concurrent access.

Ontologies to Semantic

Describe the solution you'd like
Take the semantic logic that is currently situated in the SENSE fronted and transfer it over into Filip.
Further this logic needs to be transformed to better synergies with Filip entities.

Instead of the currently used instances that are only transformed to Filip entities when saving the state, a wrapper will be written to simply extend the entities with the needed semantic functionalities.

To make the storage and reparsing of the semantic vocabulary much easier the ontology files will be saved inside the pydantic vocabulary object, which can be stored as json.

If this feature is finished a user can provide a semantic structure to Filip by giving ontologies, and use this structure to create models, connect them and model a state.

simple_ql: QueryStatement.parse_str regex

Describe the bug
Parsing of queries containing special characters in attribute name returns None.
This behavior is caused by the used regular expression rf"^\w(\w*|\.(?=\w))*{op}\w*"

To Reproduce
QueryStatement.parse_str('diffuse-radiation!=\'123\'') returns None

Expected behavior
As described in the Specification, attribute names may include all special characters except control characters, whitespace, &, ?, / and #. Therefore the statement above should return a valid QueryStatement.

Complete device update

Is your feature request related to a problem? Please describe.
When using update_device to push made changes in a device to Fiware, the device in the iota client is correctly updated, but the corresponding entity is not. Here only new attributes are added, but removed attributes are not deleted and changed values are not updated. Further changed device_settings as transport are not taken over to Fiware.

Currently the only reliable way to take over all changes is to delete the device and the corresponding entity and to repost them.

Describe the solution you'd like
To make the interaction here much cleaner, I propose the method patch_device (linked to Issue 21), that takes a device model object and makes all the needed updates for the user to take over all made changes to Fiware. It will internaly delete and repost the device only if the main device settings (endpoint,..) were changed, else it will use the methods update_device and patch_entity to update the stats.

This issue will also provide the tests to ensure the correctness of the functions (and a test for update_device, that is still missing). Further a few simple quality of live methods as does_device_exist are introduced.

Deleting complet state of an object

Is your feature request related to a problem? Please describe.
If the user creates a device a context entity is automaticaly created. But when deleting a device the entity is not automaticaly removed. Same if the linked entity is removed. This can be quite confussing for the user, as it is behaviour that is not suspected, and can lead to issues, as remenants of objects that are thought to be deleted still contiune existing.

Describe the solution you'd like
A parameter option for the delete methods, that allows the user to clear the whole state of the object with one methode call.
Even if the user does not use this optional parameter, it makes aware that the methode does not normally cleans the whole state.

Describe alternatives you've considered
None

Running Tests in CI

Creating and testing a github action to run all tests automaticaly on a PUSH.

Refactor Examples

Refactoring all examples to match structure of semantics examples, achieving a coherent style and the ability to parse them all to Jupyter notebooks

Missing Tests for DeviceModels

The current test landscape leaves a lot untested for the DeviceModels.

New tests need to be created to cover all details in the device model creation process and if the created models can be correctly transferred to Fiware.

Support for python 3.9

Is your feature request related to a problem? Please describe.
Support python 3.9 by dropping support for PyTables.

Describe the solution you'd like
Make tables support optional.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
PyTables/PyTables#823

fix data package

Describe the bug
Apparently there are still errors when installing filip

To Reproduce
Steps to reproduce the behavior:

  1. pip install .
  2. pip uninstall filip
    The first does not copy the hdf file properly
    The second one would leave fragments

Expected behavior
Both commands should work

Dont set the basicConfig of the logging module

You are doing

logging.basicConfig(level=settings.LOGLEVEL,
                    format='%(asctime)s - FiLiP.%(name)s - %(levelname)s: %('
                           'message)s',
                    datefmt='%Y-%m-%d %H:%M:%S')

in config.py.
This way, you change the settings for all other modules as well.
the LOGLEVL should be set by the user, not you.

PATCH request remains in PENDING state / handling of cmdexe

What is the issue?

When sending a post_command request to the cb and querying the entity state, the set point status may change to PENDING and will not respond to any further requests.

Proposal

The issue might be related to the cmdexe (see https://github.com/FIWARE/tutorials.IoT-Agent-JSON#southbound-traffic-commands) and the cb expecting to receive an acknowledgement from the device.
As many device might not offer an acknowledgement, this should be optional/settable by the user.
If applied, the cmdexe handling still requires implementation.

improve documentaton

Is your feature request related to a problem? Please describe.
Currently the docs are far from perfect. we want to improve them for new users.

Describe the solution you'd like
Refactor the docs and add more examples

Refactor test environments

  • Removing all the now unneeded .env.fillip
  • Adding a new .env to be used for local development
  • Adapting tests that rely on the additional config files

StaticDeviceAttribute Metadata Type

Describe the bug
Currently the StaticDevice metadata field allows the type Optional[Dict[str, Dict]]. But Fiware only allows a very specific Dict structure. Giving any other structure results in a success in Filip, but an uncatched background error in Fiware.

To Reproduce
Steps to reproduce the behavior:

  1. Create an ContextDevice containing a StaticDeviceAttribute with the metadata: {"meta": { "test": "1" }}
  2. Filip allows this assignment, you can now post the device without error
  3. But if you now look in Fiware, no device or corresponding ContextEntity appeared.

Expected behavior
FiLiP tells you, that the assignment of the metadata was not valid, and stops the execution

Fix
Change the type of the StaticDevice metadata field to a BaseModel modeling the allowed structure. The ContextMetadata and NamedContextMetadata modeld in context.py, can probably be reused for this task. The StaticDeviceAttribute metadata field would then have the same structure and logic as the ContextAttribute metadata field.

IRI as Datatype

When using Filip for the Cloud Sense Semantic App, each Entity and each Entitiyattribute has an entry that states the IRI this object/attribute is symbolising. This can be done with Datatype.Text, but to better symbolize the meaning of these fields an new Datatype coulb be introduced. Due to the fact that it is not a random char sequence but an concrete identifier of the semantic web.

QuantumLeap request pagination

Is your feature request related to a problem? Please describe.
QuantumLeap API implements a pagination mechanism in order to help clients to retrieve large sets of resources. (https://quantumleap.readthedocs.io/en/latest/user/pagination/)
However, this mechanism has not yet been implemented in the QuantumLeap client (see at https://github.com/RWTH-EBC/FiLiP/blob/development/filip/clients/ngsi_v2/quantumleap.py). Hence, the maximum number of results is limited to 10000 for a single request.

Describe the solution you'd like
The pagination mechanism is somewhat similar to the one already implemented for the context broker, compare https://github.com/RWTH-EBC/FiLiP/blob/development/filip/clients/ngsi_v2/cb.py (and also see https://fiware-orion.readthedocs.io/en/master/user/pagination/index.html). So, the solution should follow a similar approach.
However, the response is different, which results in a few changes, for instance, the json objects cannot be extended but rather the resulting data lists should be extended.
Please find a suggestion below:

def __pagination(*,
                method: PaginationMethod = PaginationMethod.GET,
                url: str,
                headers: Dict,
                limit: Union[PositiveInt, PositiveFloat] = None,
                offset: int = None,
                session: requests.Session = None,
                params: Dict = None,
                data: str = None) -> List[Dict]:
        """
        NGSIv2 implements a pagination mechanism in order to help clients to
        retrieve large sets of resources. This mechanism works for all listing
        operations in the API (e.g. GET /v2/entities, GET /v2/subscriptions,
        POST /v2/op/query, etc.). This function helps getting datasets that are
        larger than the limit for the different GET operations.
        https://fiware-orion.readthedocs.io/en/master/user/pagination/index.html
        Args:
            url: Information about the url, obtained from the original function
            headers: The headers from the original function
            params:
            limit:
        Returns:
            object:
        """
        if limit is None:
            limit = inf
        if limit > 10000:
            params['limit'] = 10000  # maximum items per request
        else:
            params['limit'] = limit
        if offset is None:
            params['offset'] = 0
        else:
            params['offset'] = offset
        additional_offset = 0
        if not session:
            session = requests.Session()
        with session:
            res = session.request(method=method,
                                  url=url,
                                  params=params,
                                  headers=headers,
                                  data=data)
            if res.ok:
                items = res.json()
                # do pagination
                count = int(res.headers['Content-Length'])
                attributes = params['attrs']

                # fresh start
                items['index'] = []
                items['attributes'][0]['values'] = []

                while len(items['index']) < limit and len(items['index']) < count:
                    try:
                        # Establishing the offset from where entities are retrieved
                        for attr in attributes:
                            params['attrs'] = attr
                            params['offset'] = len(items['index']) + additional_offset
                            params['limit'] = min(10000, (limit - len(items['index'])))
                            res = session.request(method=method,
                                                  url=url,
                                                  params=params,
                                                  headers=headers,
                                                  data=data)
                            if res.ok:
                                # items.extend(res.json()) --> this does not work for the given response structure
                                if len(items['attributes']) == len(attributes): # update entries
                                    i = find(lst=items['attributes'],key=attr)
                                    items['attributes'][i]['values'].extend(res.json()['attributes'][0]['values'])
                                elif len(items['attributes']) < len(attributes):
                                    items['attributes'].extend(res.json()['attributes'])
                                else:
                                    logger.error('Inconsistent number of attributes %i', len(items['attributes']))
                            else:
                                res.raise_for_status()
                        items['index'].extend(res.json()['index'])
                    except Exception as e:
                        if '404 Client Error' in e.args[0]:
                            # no records found, skip period
                            limit -= 10000
                            additional_offset += 10000
                        else:
                            print(e)
                    if not (pytz.utc.localize(dateutil.parser.parse(params['toDate']))>
                        dateutil.parser.parse(items['index'][-1])+datetime.timedelta(seconds=1)):
                        break
                logger.debug('Received: %s', items)
                items['entity_id'] = params['entity_id']
                items['entity_type'] = params['entity_type']
                ts = parse_obj_as(TimeSeries, items)
                return ts
            res.raise_for_status()

Describe alternatives you've considered
The obvious alternative is to individually evoke single requests and post-process the results to the desired format.

Additional context
Beside the different response structure, when there are no records within a period, the function is stuck since the request will fail and neither the items nor the limit will be updated. This exception has to be caught. Note that in the above example, the request of several attributes has been considered.

Issue saving complex information in StaticDeviceAttributes

There are some issues with adding complex information (with Enums) to value fields in DeviceAttributes. The here describe issue could also be happening for Context Attribute, this was not yet tested. Below are two approches that I took to save a complex Basemodel in a value field of a StaticDeviceAttribute, both with there own issues.

class DeviceAttribute(Basemodel):
	name: str
    attribute_type: DeviceAttributeType

if we have a DeviceAttribute da, we can export the model in 2 forms:

da.dict()
	=> {'name': 'd1', 'attribute_type': <DeviceAttributeType.lazy: 'lazy'>}
da.json()
	=> {"name": "d1", "attribute_type": "lazy"}

If we add the da export to a values array:

v1 = values.append(da.dict()) 
	=> [{'name': 'd1', 'attribute_type': <DeviceAttributeType.lazy: 'lazy'>}]
v2 = values.append(da.json()) 
	=> ['{"name": "d1", "attribute_type": "lazy"}'] 

If we add the values array to a StaticDeviceAttribute:

attr = iot.StaticDeviceAttribute(
		name="attributeName",
		type=DataType.STRUCTUREDVALUE,
		value= vN,
		entity_name=None,
		entity_type=None,
		reverse=None,
		expression=None,
		metadata=None
	))

With vN = v1:
attr => name='attributeName' ... value={'name': 'attribute_type'}
With vN = v2:
attr => name='attributeName' ... value=['{"name": "d1", "attribute_type": "lazy"}']

The dict() variant gets strangely transformed.
The json() variant does look correct and can be posted without error, but the device containing this attribute and its corresponding context entity will not appear in Fiware.

Currently I can not think of a reason for any of those two.

Field "expressionLanguage" in Device Model is not correct

The Field "expressionLanguage" in Device Model is not correct

  • It is states in the description that it is a boolean value, and that it has the possible values legacy or jexl. And is of type ExpressionLangauge.

  • It is described as an Optional Field, with the default value of legacy. But it has no default value, as a result the user needs to explicitly state the value of this field for each Device that he creates

    expressionLanguage: Optional[ExpressionLanguage] = Field(
    description="optional boolean value, to set expression language used "
    "to compute expressions, possible values are: "
    "legacy or jexl. When not set or wrongly set, legacy "
    "is used as default value."
    )

DeviceAttribute; @validator('metadata')

Describe the bug
The validator of the DeviceAttribute Model in iot.py, should accept:
Optional[Dict[str, Union[Dict, str]]]

But it throws an error on the values: None, {"test", "testing"}. Both values are correct and can be successfully treated by the post_device methode.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new DeviceAttribute object with one of the stated values in the metadata field.

Expected behavior
No Error

Python Docstring: Raises missing

Most methods are missing the Raises part in the Docstring commands.

Some are informing about possible Error raises in the description, but not all.

I would suggest adding the Raises tag and detail information to all methods that could raise an error. With this it is directly clear to the user if he needs to handle errors and which types to expect.

Introduce concurrent testing

Is your feature request related to a problem? Please describe.
Currently, concurrent testing will automatically interfere with each other because the servicepaths are static. Therefore, the tests will all use the same tenants which will result in failing tests, if they try to access the same resources.

Describe the solution you'd like
The idea is to introduce a TestingSettings-class that will check for a local environment for its variables. If a *.env. is not available it will try to use environment variables. These variables should be set in the CI because the CI should not contain a file with information about the used servers. The servicepath should then be either autogenerated or set in the first or second way.

client log does not output messages

Apparently, there is a minor bug in the client log function. It checks for the wrong existence of the response objekt.

if err.response is not None:
    ....output message

Device BaseAttribute; entity_name and entity_type

Describe the bug
The description of the field states:

"entity_name: the presence of this attribute indicates "
"that the value will not be stored in the original device "
"entity but in a new entity with an ID given by this "
"attribute. The type of this additional entity can be "
"configured with the entity_type attribute. If no type is "
"configured, the device entity type is used instead. "

But if a value other than None is given (see other issue: we need to always state a value, even if we want None) the Attribute does not appear in the context broker.

If the entity_id and type are equal to the device info, it does not appear in the device (this is an edge case, and could be an expected behaviour)
But if some other value is given no entity is created with the given id and type, thus the attribute is not present in the context broker.

To Reproduce
Steps to reproduce the behavior:

  1. Create a device object
  2. Add some Attribute to it, with entity_name and entitiy_type no null
  3. post_device

Expected behavior
A new entity with (entity_name and entity_type) is present in the ContextBroker and holds the attribute

move back to simplier docs design

currently, pydantic models are not rendered very well in the material design. Therefore, we want to move back to the readthedocs design

Semantics: Flexible model generation output

Currently the generate_vocabulary_models always produces a python file with the given path and filename.

To be more flexible with its usage, it should only save the models if both path and filename are given, else it returns the file-content as string.

This opens the possibilities for easier transference of models to a backend server. It is an optional feature which does not impact any currently implemented logic.

Couldn't update subscription with default values

Describe the bug
Method update_subscription of filip.clients.ngsi_v2.ContextBrokerClient has following configuration for request serialization:

res = self.patch(
                url=url,
                headers=headers,
                data=subscription.json(exclude={'id'},
                                       exclude_unset=True,
                                       exclude_defaults=True,
                                       exclude_none=True))

If a subscription is created/updated with non default values you can never re-set the default ones because defaults are excluded from serialization.

To Reproduce
Steps to reproduce the behavior:

As an example try to update the status of a subscription:

        with ContextBrokerClient(url='http://localhost:1026',
                                 fiware_header=FiwareHeader(
                                     service='fw-service',
                                     service_path='/testing',
                                 )) \
                as cb_client:

            subscription = cb_client.get_subscription('xyz')
            subscription.status = Status.INACTIVE

            cb_client.update_subscription(subscription)

โ†’ subscription updates status to "inactive"

            subscription.status = Status.ACTIVE
            cb_client.update_subscription(subscription)

โ†’ subscription still has status "inactive"

Environment (please complete the following information):

  • OS: Windows 10
  • Version 20H2
  • Python 3.8

Semantics: Better load function interface

This issue will make the search for existing semantic objects and their loading more flexible by including more of the query parameters that get_entity_list() offers in load_instances_from_fiware().

Post_subscription prevent duplicates

Prevent that post_subscription (ngsi_v2.cb.py) creates a duplicate entry.

The methode shall now check, if the exact same subscription already exists.
If yes, it makes a log entry and returns the ID of the already created subscription

Semantic Instances: Name and Comment

All semantic instance should hold two variables: name, comment that the user can fill out to keep a better overview of the instances.

This feature is mainly inspired by the needs of the SENSE app, but it can be a useful tool for each instance organistation.
And as it is optional, it does not really disturb if it is not used (only an unused additional field in the CB).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.