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
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 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)
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)
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)
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 })
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()
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'}))
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)
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)
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))
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
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)
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" ] }
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.
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, [])
""" 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
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()
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()
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
# 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,