def delete_subscription(self, subscription_id: str): url = self.url + '/v2/subscriptions/' + subscription_id response = self.session.delete(url, headers=self.get_header()) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def delete(self, entity_id: str): url = self.url + '/v2/entities/' + entity_id response = self.session.delete(url, headers=self.get_header()) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def get_subjects(self, object_entity_name: str, object_entity_type: str, subject_type=None): """ Function gets the JSON for child / subject entities for a parent / object entity. :param object_entity_name: The parent / object entity name :param object_entity_type: The type of the parent / object entity :param subject_type: optional parameter, if added only those child / subject entities are returned that match the type :return: JSON containing the child / subject information """ url = self.url + '/v2/entities/?q=ref' + object_entity_type + '==' + object_entity_name + '&options=count' if subject_type is not None: url = url + '&attrs=type&type=' + subject_type headers = self.get_header() response = self.session.get( url=url, headers=headers, ) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def add_attribute(self, entity: Entity = None, entity_name: str = None, attr_dict: dict = None): # POST /v2/entities/{id}/attrs?options=append """ This function adds attributes to the Entity in the Context Broker. This can be done in two ways, either by first adding the attribute to the Entity object or by directly sending it from a dict/JSON The Function first compares it with existing attributes, and only adds (so updates) the ones not previoulsy existing :param entity: The updated Entity Instance :param entity_name: The Entity name which should be updated :param attribute_dict: A JSON/Dict containing the attributes :return: - """ if isinstance(entity, Entity): attributes = entity.get_attributes() entity_name = entity.id else: attributes = attr_dict entity_name = entity_name existing_attributes = self.get_attributes(entity_name) new_attributes = { k: v for (k, v) in attributes.items() if k not in existing_attributes } url = self.url + '/v2/entities/' + entity_name + '/attrs?options=append' headers = self.get_header(requtils.HEADER_CONTENT_JSON) data = json.dumps(new_attributes) response = self.session.post(url, data=data, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def post_json(self, json=None, entity=None, params=None): """ Function registers a JSON with the Orion Context Broker. :param json: A JSON (dictionary) :param entity: An Orion entity, from which the json_data can be obatained. :param params: :return: """ headers = self.get_header(requtils.HEADER_CONTENT_JSON) if json is not None: json_data = json elif (json is None) and (entity is not None): json_data = entity.get_json() else: logger.error(f"Please provide a valid data format.") json_data = "" if params is None: url = self.url + '/v2/entities' response = self.session.post(url, headers=headers, data=json_data) else: url = self.url + "/v2/entities" + "?options=" + params response = self.session.post(url, headers=headers, data=json_data) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def remove_attributes(self, entity_name): url = self.url + '/v2/entities/' + entity_name + '/attrs' response = self.session.put(url) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, response)
def post_cmd_v1(self, entity_id: str, entity_type: str, cmd_name: str, cmd_value: str): url = self.url + '/v1/updateContext' payload = { "updateAction": "UPDATE", "contextElements": [{ "id": entity_id, "type": entity_type, "isPattern": "false", "attributes": [{ "name": cmd_name, "type": "command", "value": cmd_value }] }] } headers = self.get_header(requtils.HEADER_CONTENT_JSON) data = json.dumps(payload) response = self.session.post(url, headers=headers, data=data) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def get_entity_attribute_json(self, entity_name, attr_name): url = self.url + '/v2/entities/' + entity_name + '/attrs/' + attr_name response = self.session.get(url, headers=self.get_header()) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def update_entity(self, entity): url = self.url + '/v2/entities/' + entity.id + '/attrs' payload = entity.get_attributes_key_values() headers = self.get_header(requtils.HEADER_CONTENT_JSON) data = json.dumps(payload) response = self.session.patch(url, headers=headers, data=data) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def update_attribute(self, entity_name, attr_name, attr_value): url = self.url + '/v2/entities/' + entity_name + '/attrs/' \ + attr_name + '/value' headers = self.get_header(requtils.HEADER_CONTENT_PLAIN) data = json.dumps(attr_value) response = self.session.put(url, headers=headers, data=data) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def get_groups(self, device_group: DeviceGroup): url = self.url + '/iot/services' headers = device_group.get_header() response = self.session.request("GET", url, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def post_json_key_value(self, json_data=None, params="keyValues"): """ :param json_data: :param params: :return: """ headers = self.get_header(requtils.HEADER_CONTENT_JSON) url = self.url + "/v2/entities" + "?options=" + params response = self.session.post(url, headers=headers, data=json_data) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def get_entity(self, entity_name, entity_params=None): url = self.url + '/v2/entities/' + entity_name headers = self.get_header() if entity_params is None: response = self.session.get(url, headers=headers) else: response = self.session.get(url, headers=headers, params=entity_params) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def delete_group(self, device_group: DeviceGroup): url = self.url + '/iot/services' headers = device_group.get_header() querystring = { "resource": device_group.get_resource(), "apikey": device_group.get_apikey() } response = self.session.request("DELETE", url, headers=headers, params=querystring) if response.status_code == 204: log.info(f"Device group successfully deleted!") else: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def get_pagination(self, url: str, headers: dict, count: float, limit: int = 20, params=None): """ 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. :param url: Information about the url, obtained from the orginal function e.g. : http://localhost:1026/v2/subscriptions?limit=20&options=count :param headers: The headers from the original function, e.g: {'fiware-service': 'crio', 'fiware-servicepath': '/measurements'} :param count: Number of total elements, obtained by adding "&options=count" to the url, included in the response headers :param limit: Limit, obtained from the oringal function, default is 20 :return: A list, containing all objects in a dictionary """ all_data = [] # due to a math, one of the both numbers has to be a float, # otherwise the value is rounded down not up no_intervals = int(math.ceil(count / limit)) for i in range(0, no_intervals): offset = str(i * limit) if i == 0: url = url else: url = url + '&offset=' + offset if params == (not None): response = self.session.get(url=url, headers=headers, params=params) else: response = self.session.get(url=url, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: for resp_dict in json.loads(response.text): all_data.append(resp_dict) return all_data
def post_relationship(self, json_data=None): """ Function can be used to post a one to many or one to one relationship. :param json_data: Relationship Data obtained from the Relationship class. e.g. : {"id": "urn:ngsi-ld:Shelf:unit001", "type": "Shelf", "refStore": {"type": "Relationship", "value": "urn:ngsi-ld:Store:001"}} Can be a one to one or a one to many relationship """ url = self.url + '/v2/op/update' headers = self.get_header(requtils.HEADER_CONTENT_JSON) # Action type append required, # Will overwrite existing entities if they exist whereas # the entities attribute holds an array of entities we wish to update. payload = {"actionType": "APPEND", "entities": [json.loads(json_data)]} data = json.dumps(payload) response = self.session.post(url=url, data=data, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr)
def get_device(self, device_group: DeviceGroup, device: Device): """ Function gets a device. :param device_group: :param device: :return: """ url = self.url + '/iot/devices/' + device.device_id headers = {**requtils.HEADER_CONTENT_JSON, **device_group.get_header()} payload = "" response = self.session.request("GET", url, data=payload, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def get_subscription_list(self, limit=100): url = self.url + '/v2/subscriptions?options=count' response = self.session.get(url, headers=self.get_header()) sub_count = float(response.headers["Fiware-Total-Count"]) if sub_count >= limit: response = self.get_pagination(url=url, headers=self.get_header(), limit=limit, count=sub_count) return response ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) return None json_object = json.loads(response.text) subscriptions = [] for key in json_object: subscriptions.append(key["id"]) return subscriptions
def update_device(self, device_group: DeviceGroup, device: Device, payload: dict): """ :param device_group: :param device: :param payload: :return: """ url = self.url + '/iot/devices/' + device.device_id headers = {**requtils.HEADER_CONTENT_JSON, **device_group.get_header()} response = self.session.request("PUT", url, data=payload, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: log.info(f"Device {device.device_id} successfully updated!")
def get_entities_list(self, limit=100) -> list: url = self.url + '/v2/entities?options=count' header = self.get_header(requtils.HEADER_ACCEPT_JSON) response = self.session.get(url, headers=header) sub_count = float(response.headers["Fiware-Total-Count"]) if sub_count >= limit: response = self.get_pagination(url=url, headers=header, limit=limit, count=sub_count) return response ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) return None else: json_object = json.loads(response.text) entities = [] for key in json_object: entities.append(key["id"]) return entities
def get_all_entities(self, parameter=None, parameter_value=None, limit=100): url = self.url + '/v2/entities?options=count' headers = self.get_header() if parameter is None and parameter_value is None: response = self.session.get(url, headers=headers) sub_count = float(response.headers["Fiware-Total-Count"]) if sub_count >= limit: response = self.get_pagination(url=url, headers=headers, limit=limit, count=sub_count) return response elif parameter is not None and parameter_value is not None: parameters = {'{}'.format(parameter): '{}'.format(parameter_value)} response = self.session.get(url, headers=headers, params=parameters) sub_count = float(response.headers["Fiware-Total-Count"]) if sub_count >= limit: response = self.get_pagination(url=url, headers=headers, limit=limit, count=sub_count, params=parameters) return response else: logger.error( "Getting all entities: both function parameters have to be 'not null'" ) return None ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def get_objects(self, subject_entity_name: str, subject_entity_type: str, object_type=None): """ Function returns a List of all objects associated to a subject. If object type is not None, only those are returned, that match the object type. :param subject_entity_name: The child / subject entity name :param subject_entity_type: The type of the child / subject entity :param object_type: :return: List containing all associated objects """ url = self.url + '/v2/entities/' + subject_entity_name + '/?type=' + subject_entity_type + '&options=keyValues' if object_type is not None: url = url + '&attrs=ref' + object_type headers = self.get_header() response = self.session.get(url=url, headers=headers) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: return response.text
def update_group(self, device_group: DeviceGroup): url = self.url + '/iot/services' headers = { **requtils.HEADER_CONTENT_JSON, **device_group.get_header_last() } querystring = { "resource": device_group.get_resource_last(), "apikey": device_group.get_apikey_last() } payload = json.loads(device_group.get_json()) payload = json.dumps(payload, indent=4) log.info(f" {datetime.datetime.now()} - Update group with: {payload}") response = self.session.request("PUT", url, data=payload, headers=headers, params=querystring) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) else: log.info(f"Device group sucessfully updated")
def post_entity(self, entity: Entity, force_update: bool = True): """ Function registers an Object with the Orion Context Broker, if it allready exists it can be automatically updated if the overwrite bool is True First a post request with the entity is tried, if the response code is 422 the entity is uncrossable, as it already exists there are two options, either overwrite it, if the attribute have changed (e.g. at least one new/ new values) (update = True) or leave it the way it is (update=False) :param entity: An entity object :param update: If the response.status_code is 422, whether the old entity should be updated or not :return: """ url = self.url + '/v2/entities' headers = self.get_header(requtils.HEADER_CONTENT_JSON) data = entity.get_json() response = self.session.post(url, headers=headers, data=data) ok, retstr = requtils.response_ok(response) if not ok: if (response.status_code == 422) & (force_update is True): url += f"{entity.id}/attrs" response = self.session.post(url, headers=headers, data=data) ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, response)
def create_subscription(self, subscription_body, check_duplicate: bool = True): url = self.url + '/v2/subscriptions' headers = self.get_header(requtils.HEADER_CONTENT_JSON) if check_duplicate is True: exists = self.check_duplicate_subscription(subscription_body) if exists is True: logger.info(f"A similar subscription already exists.") response = self.session.post(url, headers=headers, data=subscription_body) if response.headers is None: return ok, retstr = requtils.response_ok(response) if not ok: level, retstr = requtils.logging_switch(response) self.log_switch(level, retstr) return None else: location = response.headers.get('Location') addr_parts = location.split('/') subscription_id = addr_parts.pop() return subscription_id